DeepSeek API Examples: Copy-Paste Snippets for Flash and V4-Pro

DeepSeek API examples for deepseek-flash and deepseek-v4-pro: requests, multi-turn, streaming, thinking, JSON, tools, FIM, prefix completion and costs.

API·April 25, 2026·By DS Guide Editorial
DeepSeek API examples tutorial card, subtitle 'Five copy-paste patterns covering V4 production calls', listing a minimal POST /chat/completions, streaming with stream=true (SSE), JSON output via response_format, tool calls via tools[] plus JSON Schema, and thinking mode via reasoning_effort.

You opened the DeepSeek docs, found a quickstart, and now you want the next ten things — streaming, JSON output, tool calls, thinking mode, cost math that survives a code review. This page collects DeepSeek API examples for the two current models, deepseek-flash and deepseek-v4-pro, which replaced the legacy deepseek-chat and deepseek-reasoner IDs. Every snippet targets the OpenAI-compatible endpoint at https://api.deepseek.com and uses only fields documented in DeepSeek’s API reference and guides, with notes on what breaks, what costs more than you think, and which features are still Beta. By the end you will have copy-paste code for the eight most common API patterns, plus a cost helper for both models.

What the DeepSeek API actually is

Title card: eyebrow 'API · Request shapes', title 'Request Shapes', tagline 'Chat, streaming, tools and Beta FIM; no embeddings API.', and four stats: Chat, Chat Completions; SSE, stream=true; Tools, function calls; and FIM, Beta completions, beside a punch-card illustration.

DeepSeek’s API is an HTTP service that speaks the OpenAI Chat Completions wire format. The canonical chat endpoint is POST /chat/completions against the base URL https://api.deepseek.com. DeepSeek’s official quickstart shows the same shape — a JSON body with model, messages, and the usual sampling knobs.

Two practical points before any code:

  • The API is stateless. Unlike the web chat or mobile app, the API does not remember prior turns. Each request must include the full conversation history in messages.
  • Two current model IDs. deepseek-flash is served by DeepSeek-V4.1-Flash-1017 (see DeepSeek V4-Flash for the Flash line) and is the only current model with image input; deepseek-v4-pro is served by DeepSeek-V4-Pro-0813 (see DeepSeek V4-Pro). Both publish MIT-licensed weights, both have a 1M-token context with output up to 384K tokens, and both run in thinking mode by default.

The legacy deepseek-chat and deepseek-reasoner IDs were scheduled for retirement on 2026-07-24 at 15:59 UTC (until then they routed to deepseek-v4-flash in non-thinking and thinking mode) and are no longer listed in DeepSeek’s docs. deepseek-v4-flash itself is now a legacy name served by DeepSeek-V4.1-Flash-1017. Migration is a one-line change to your model= argument; base_url stays put. For background on the model family see our DeepSeek V4 overview.

Example 1: Minimal request — curl and Python

The simplest possible call, with the default thinking mode. First in curl:

curl https://api.deepseek.com/chat/completions \
  -H "Authorization: Bearer $DEEPSEEK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-flash",
    "messages": [
      {"role": "system", "content": "You are a terse senior engineer."},
      {"role": "user", "content": "What is a MoE router, in two sentences?"}
    ]
  }'

Then the equivalent in Python with the OpenAI SDK — no rewrites, just swap the base URL. This version switches thinking off so that the temperature setting takes effect:

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ.get("DEEPSEEK_API_KEY"),
    base_url="https://api.deepseek.com",
)

resp = client.chat.completions.create(
    model="deepseek-flash",
    messages=[
        {"role": "system", "content": "You are a terse senior engineer."},
        {"role": "user", "content": "What is a MoE router, in two sentences?"},
    ],
    temperature=1.3,
    extra_body={"thinking": {"type": "disabled"}},
)
print(resp.choices[0].message.content)

Note temperature=1.3. DeepSeek publishes task-specific recommendations: 0.0 for code and math, 1.0 for data analysis, 1.3 for general chat and translation, 1.5 for creative writing. They apply in non-thinking mode only — thinking mode (the default) accepts temperature but ignores it. The examples below reuse this client.

If your codebase already speaks Anthropic, the API also supports the Anthropic format at a separate base URL, https://api.deepseek.com/anthropic, so the Anthropic SDK works too. More on that in our DeepSeek OpenAI SDK compatibility guide.

Example 2: Multi-turn conversation (resending history)

Because the API is stateless, you maintain the conversation client-side:

history = [
    {"role": "system", "content": "You are a Postgres tutor."},
]

def ask(user_msg: str) -> str:
    history.append({"role": "user", "content": user_msg})
    resp = client.chat.completions.create(
        model="deepseek-flash",
        messages=history,
        temperature=1.3,
        extra_body={"thinking": {"type": "disabled"}},
    )
    answer = resp.choices[0].message.content
    history.append({"role": "assistant", "content": answer})
    return answer

print(ask("Explain CTEs in one paragraph."))
print(ask("Show a recursive example."))

Every call resends the entire history array. That sounds wasteful, but DeepSeek’s automatic context cache persists a prefix unit at the end of each request’s output, so the next turn — which resends that exact history plus a new question — can bill the older tokens at the cache-hit rate (best-effort). We dig into that further in DeepSeek context caching.

Example 3: Streaming responses

For chat UIs you want tokens as they generate. Set stream=True and iterate:

stream = client.chat.completions.create(
    model="deepseek-flash",
    messages=[{"role": "user", "content": "Write a haiku about caching."}],
    stream=True,
    temperature=1.5,
    extra_body={"thinking": {"type": "disabled"}},
)
for chunk in stream:
    delta = chunk.choices[0].delta.content or ""
    print(delta, end="", flush=True)

When thinking mode is on, reasoning streams in a separate delta.reasoning_content field before the final content begins, and the last chunk before data: [DONE] carries the token usage. Detailed patterns live in DeepSeek API streaming.

Example 4: Thinking mode (reasoning_effort)

Title card: eyebrow 'Example · Thinking mode', title 'Thinking Mode', tagline 'On by default; reasoning_content comes before content.', and four stats: High default effort, Low lighter effort, Max for the hardest tasks, and 128K default output limit at max effort, beside a typewriter illustration.

The current models collapse the old “chat vs reasoner” split into a parameter on either model. Thinking is on by default with effort high; reasoning_effort takes "low", "high" or "max", and the thinking flag goes through extra_body:

resp = client.chat.completions.create(
    model="deepseek-v4-pro",
    messages=[{"role": "user",
               "content": "Plan a zero-downtime migration from MySQL 5.7 to 8.0."}],
    reasoning_effort="high",
    extra_body={"thinking": {"type": "enabled"}},
    max_tokens=8192,
)
msg = resp.choices[0].message
print("REASONING:\n", msg.reasoning_content)
print("ANSWER:\n", msg.content)

The response returns reasoning_content alongside the final content. Use reasoning_effort="max" for the heaviest workloads; per the API reference, max_tokens then defaults to 128K (64K at the other thinking levels), and you can set it up to 393,216. A low max_tokens like the 8192 above can cut a long reasoning run short (finish_reason="length"). Keep thinking off for simple chat: it spends output tokens on reasoning you may not need.

Example 5: JSON mode

For structured extraction set response_format={"type": "json_object"}. JSON mode is designed to return valid JSON, but DeepSeek’s JSON Output guide notes the API may occasionally return empty content — three rules apply:

  1. Include the word “json” in the system or user prompt.
  2. Show a small example of the schema you want.
  3. Set max_tokens high enough that output cannot be truncated mid-object.
import json

SYSTEM = """Extract invoice fields as json.
Example:
{"invoice_no": "INV-001", "total_usd": 42.50, "line_items": 3}
"""

resp = client.chat.completions.create(
    model="deepseek-flash",
    messages=[
        {"role": "system", "content": SYSTEM},
        {"role": "user", "content": open("invoice.txt").read()},
    ],
    response_format={"type": "json_object"},
    max_tokens=2048,
    temperature=0.0,
    extra_body={"thinking": {"type": "disabled"}},
)
data = json.loads(resp.choices[0].message.content or "{}")

Handle the empty-content case explicitly — that or "{}" exists for a reason. More patterns in DeepSeek API JSON mode.

Example 6: Tool calling (function calling)

Tool calling uses the OpenAI-compatible schema, supported in both thinking and non-thinking modes. This version runs the full round trip; appending the assistant message object (rather than rebuilding it) keeps its reasoning_content, which thinking mode requires you to pass back whenever the request carries tools:

import json

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get current weather for a city.",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"],
        },
    },
}]

def get_weather(city: str) -> str:
    return f"14°C and cloudy in {city}"  # replace with a real lookup

messages = [{"role": "user", "content": "Weather in Dublin?"}]
resp = client.chat.completions.create(model="deepseek-flash", messages=messages, tools=tools)
msg = resp.choices[0].message
messages.append(msg)

for call in msg.tool_calls or []:
    args = json.loads(call.function.arguments)  # validate before use
    messages.append({"role": "tool", "tool_call_id": call.id,
                     "content": get_weather(**args)})

if msg.tool_calls:
    resp = client.chat.completions.create(model="deepseek-flash", messages=messages, tools=tools)
print(resp.choices[0].message.content)

DeepSeek’s API reference notes that the model does not always generate valid JSON arguments and may invent parameters, so validate them before calling your function. In thinking mode, tool_choice="required" or a named tool returns a 400; leave it at the default auto or disable thinking. See DeepSeek API function calling for strict mode and multi-step loops.

Example 7: FIM completion (Beta)

Fill-In-the-Middle is for code editors and autocomplete. It runs in non-thinking mode only, is currently Beta with a 4K maximum output, and uses the /completions endpoint under the Beta base URL:

beta = OpenAI(api_key=os.environ.get("DEEPSEEK_API_KEY"),
              base_url="https://api.deepseek.com/beta")

resp = beta.completions.create(
    model="deepseek-flash",
    prompt="def fibonacci(n):\n    if n < 2:\n        return n\n    return ",
    suffix="\n\nprint(fibonacci(10))",
    max_tokens=64,
)
print(resp.choices[0].text)

Example 8: Chat Prefix Completion (Beta)

Flat-vector diagram of DeepSeek API beta endpoints showing FIM completion and Chat Prefix Completion side by side.

When you need the model to continue from a specific opening, make the last message an assistant message with prefix: True and call the Beta base URL (the beta client from Example 7):

messages = [
    {"role": "user", "content": "Write quicksort in Python."},
    {"role": "assistant", "content": "```python\n", "prefix": True},
]
resp = beta.chat.completions.create(
    model="deepseek-v4-pro",
    messages=messages,
    stop=["```"],
)
print(resp.choices[0].message.content)

Quick parameter reference

Parameter Type Notes
model string deepseek-flash or deepseek-v4-pro
temperature 0.0–2.0 (default 1) 0.0 code/math, 1.0 analysis, 1.3 chat, 1.5 creative; no effect in thinking mode
top_p 0–1 (default 1) Model-specific: on deepseek-flash only in thinking mode (0.95–1.0); on deepseek-v4-pro only in non-thinking mode
max_tokens int 1–393,216; defaults 8K non-thinking, 64K thinking, 128K at max; set it explicitly in JSON mode
reasoning_effort string "low", "high" (default) or "max"; "none" disables thinking
thinking object (via extra_body) {"type": "enabled"} (default) or {"type": "disabled"}
stream / stream_options bool / object SSE chunks; reasoning streams separately; usage on the last chunk
response_format object {"type": "json_object"} for JSON mode
tools / tool_choice array / string or object OpenAI-shaped function definitions; required or a named tool not supported in thinking mode
stop string or array Up to 16 stop sequences

Cost worked example — both models

Prices as of October 2026, from DeepSeek’s official pricing page, per 1M tokens: deepseek-flash $0.006 cache-hit input / $0.30 cache-miss input / $1.20 output at peak and $0.003 / $0.15 / $0.60 off-peak; deepseek-v4-pro $0.044 / $1.32 / $3.96 at peak and $0.022 / $0.66 / $1.98 off-peak. Peak hours are 01:00–04:00 and 06:00–10:00 UTC, Monday through Friday, excluding Chinese public holidays; all other hours are off-peak.

The usage object on every response already splits the input into the two billed buckets, so the cost of a call is a few lines of code:

RATES = {  # USD per 1M tokens at peak, October 2026; off-peak is half
    "deepseek-flash":  {"hit": 0.006, "miss": 0.30, "out": 1.20},
    "deepseek-v4-pro": {"hit": 0.044, "miss": 1.32, "out": 3.96},
}

def request_cost(usage, model: str, off_peak: bool = False) -> float:
    r = RATES[model]
    usd = (usage.prompt_cache_hit_tokens * r["hit"]
           + usage.prompt_cache_miss_tokens * r["miss"]
           + usage.completion_tokens * r["out"]) / 1_000_000
    return usd / 2 if off_peak else usd

print(request_cost(resp.usage, "deepseek-flash"))

Worked example: one call with a 2,000-token cached system prompt, a 200-token uncached user message and a 300-token response.

Token bucket Tokens deepseek-flash peak / off-peak deepseek-v4-pro peak / off-peak
Cached input 2,000 $0.000012 / $0.000006 $0.000088 / $0.000044
Uncached input 200 $0.000060 / $0.000030 $0.000264 / $0.000132
Output 300 $0.000360 / $0.000180 $0.001188 / $0.000594
Total per call $0.000432 / $0.000216 $0.001540 / $0.000770

Two things people get wrong: skipping the uncached-input row (each new user message misses the cache against the system prefix), and mixing models inside one estimate. Pick one and stick with it. In thinking mode, reasoning tokens count as output (completion_tokens_details.reasoning_tokens), so the output row grows. For interactive estimates use the DeepSeek pricing calculator.

Error handling pattern

The API returns OpenAI-compatible error envelopes. The codes and finish reasons you will hit most often, per DeepSeek’s Error Codes page and API reference:

  • 400 Invalid Format / 422 Invalid Parameters — fix the request using the hints in the error message.
  • 401 Authentication Fails — wrong or missing API key.
  • 402 Insufficient Balance — top up the account.
  • 429 Rate Limit Reached — requests too fast or over the per-account concurrency limit (2,500 for deepseek-flash, 500 for deepseek-v4-pro); back off and retry with jitter.
  • 500 Server Error / 503 Server Overloaded — retry after a brief wait.
  • finish_reason="length" — output was truncated; raise max_tokens.
  • finish_reason="content_filter" — content was omitted by the content filter.
  • finish_reason="insufficient_system_resource" — generation was interrupted for lack of inference resources; retry.
import random
import time

from openai import APIConnectionError, APIStatusError, RateLimitError

def call_with_retry(**kw):
    for attempt in range(5):
        try:
            return client.chat.completions.create(**kw)
        except (RateLimitError, APIConnectionError):
            pass                      # 429 or network error: retry
        except APIStatusError as e:
            if e.status_code < 500:
                raise                 # other 4xx: fix the request
        time.sleep((2 ** attempt) + random.random())
    raise RuntimeError("exhausted retries")

For a complete code-by-code playbook see DeepSeek API error codes.

Where to go next

Title card: eyebrow 'Example · First call', title 'Your First Call', tagline 'POST /chat/completions with deepseek-flash.', and four stats: POST chat endpoint, Flash default model, 1M context tokens, and 384K max output, beside a compact-desktop illustration.

If you are still wiring up authentication, start with our walk-through on how to get a DeepSeek API key, then the DeepSeek API getting started tutorial. For broader context on every endpoint, parameter and rate limit, the DeepSeek API docs and guides hub indexes the lot. If you need a JavaScript counterpart to the snippets above, see DeepSeek Node.js integration.

Frequently asked questions

How do I make my first DeepSeek API call?

Get an API key from the DeepSeek platform console, install the OpenAI SDK (pip install openai), and instantiate the client with base_url="https://api.deepseek.com". Then call client.chat.completions.create with model="deepseek-flash" and a messages array. Example 1 above is a minimal call. Full setup steps live in our DeepSeek API getting started tutorial.

What is the difference between deepseek-v4-flash and deepseek-v4-pro?

deepseek-v4-flash is now a legacy name: requests that use it are served by DeepSeek-V4.1-Flash-1017 and billed at the deepseek-flash price, so use deepseek-flash in new code. deepseek-flash costs $0.30 cache-miss input / $1.20 output per million tokens at peak ($0.15 / $0.60 off-peak; cache hits $0.006 / $0.003) and is the only current model with image input. deepseek-v4-pro (DeepSeek-V4-Pro-0813) costs $1.32 / $3.96 at peak ($0.66 / $1.98 off-peak; cache hits $0.044 / $0.022). Both share the 1M-token context, 384K maximum output, thinking modes, JSON mode, tool calling and streaming. Start with Flash and move a workload to Pro only if your evals show it pays off. Compare in detail at the DeepSeek models hub.

Does the DeepSeek API remember previous messages?

No. The API is stateless: every POST /chat/completions request must include the full conversation history in messages. The web chat and mobile app keep session history, but the developer API does not. Repeated prefixes are billed at the cheaper cache-hit rate automatically once they have been persisted. See DeepSeek context caching for how to structure prompts so the cache fires.

Can I use the OpenAI Python SDK with DeepSeek?

Yes. DeepSeek’s API matches the OpenAI Chat Completions wire format. Change base_url to https://api.deepseek.com, supply your DeepSeek API key and use a DeepSeek model name — existing call sites keep working, and DeepSeek-specific fields such as thinking go in extra_body. DeepSeek also supports the Responses API on the same base URL and an Anthropic-compatible surface at https://api.deepseek.com/anthropic. The compatibility caveats are catalogued in our DeepSeek OpenAI SDK compatibility notes.

Why does DeepSeek return reasoning_content in some responses?

Thinking mode is on by default, and whenever it is on — by default or with reasoning_effort="high" and extra_body={"thinking": {"type": "enabled"}} — the model returns reasoning_content alongside the final content. The reasoning field holds the chain-of-thought the model produced before answering; the content field is the user-facing answer. Pass extra_body={"thinking": {"type": "disabled"}} if you don’t want it. Legacy deepseek-reasoner produced the same shape; it was scheduled for retirement on 2026-07-24 at 15:59 UTC. More on prompt design in our DeepSeek prompt engineering guide.

Sources & Methodology

Last source check: October 25, 2026

Primary sources

Methodology

Pricing figures were checked against the official DeepSeek pricing page and normalised into estimated monthly costs using sample token usage scenarios. Actual costs may vary depending on caching, input/output ratio, regional availability, and provider updates.

Data confidence

High — figures checked directly against the official pricing page on the review date.

Editorial note

The site's pricing dataset is fetched daily from DeepSeek's official pricing page; this article reflects the prices on the date shown above.

Leave a Reply

Your email address will not be published. Required fields are marked *