DeepSeek shipped V4 Flash 0731 on July 31, and the headline everyone quoted was the price — roughly $0.14 / $0.28 per million tokens for a model that out-benchmarks flagships on agent tasks (we ran the numbers in the cheap model that beats the flagship). This piece is the other half: how you actually call it. It's OpenAI-compatible, so the migration is two lines — but thinking mode, the split reasoning field, and a 384K output ceiling each have one gotcha worth knowing before you wire it into an agent.

1. Point your client at it — two lines#

V4 Flash implements the OpenAI Chat Completions API. Reuse the official openai SDK and change only the base URL and the model name. Set the key once — never hard-code it:

export DEEPSEEK_API_KEY="sk-..."
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["DEEPSEEK_API_KEY"],
    base_url="https://api.deepseek.com/v1",   # ← change 1
)

resp = client.chat.completions.create(
    model="deepseek-v4-flash",                # ← change 2
    messages=[{"role": "user", "content": "Summarize this changelog in 3 bullets."}],
)
print(resp.choices[0].message.content)

That call runs in non-thinking mode — fast and cheap, the right default for extraction, classification, routing, and other high-volume grunt work. Everything else in your existing agent code (tool schemas, streaming, message history) stays exactly as it is.

2. Turn thinking on — a flag, not a new model#

You don't switch models to get reasoning. Thinking is a per-request setting: pass a thinking block via extra_body and set reasoning_effort.

resp = client.chat.completions.create(
    model="deepseek-v4-flash",
    messages=[{"role": "user", "content": "Plan the migration, then write the script."}],
    extra_body={"thinking": {"type": "enabled"}},
    reasoning_effort="high",   # none disables · low/medium/high/xhigh/max
)

msg = resp.choices[0].message
print(msg.reasoning_content)   # the chain-of-thought — for your logs
print(msg.content)             # the actual answer — for your app

The effort dial is the cost dial. reasoning_effort="none" disables thinking entirely; low through max enable it at rising depth (medium and high both map to high effort). Turn it up for planning, debugging, and code generation where a wrong answer is expensive; turn it down — or off — for the calls where latency and cost beat depth.

The gotcha: the reasoning comes back as a separate field, reasoning_content, distinct from content. Log it, inspect it, throw it away — but never concatenate it into the assistant's turn or feed it back into the next request as message content. It's not part of the answer, and re-injecting it corrupts the conversation and inflates your input bill.

3. curl and Node — the same two changes#

curl https://api.deepseek.com/v1/chat/completions \
  -H "Authorization: Bearer $DEEPSEEK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-v4-flash",
    "messages": [{"role": "user", "content": "ping"}],
    "thinking": {"type": "enabled"},
    "reasoning_effort": "low"
  }'
import OpenAI from "openai";

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

const resp = await client.chat.completions.create({
  model: "deepseek-v4-flash",
  messages: [{ role: "user", content: "Refactor this function." }],
  reasoning_effort: "high",
  // @ts-expect-error DeepSeek extension
  thinking: { type: "enabled" },
});
console.log(resp.choices[0].message.content);

4. The Responses API — reasoning arrives as its own item#

V4 Flash also supports the Responses API, the stateful, item-based interface. The shape is different from Chat Completions in one way that matters: in thinking mode the chain-of-thought is emitted as a reasoning item that appears before the message item in the output array. Tool calls come back as function_call items and server-side web searches as web_search_call items.

So don't grab output[0] and assume it's the answer — walk the array and pull the message item:

resp = client.responses.create(
    model="deepseek-v4-flash",
    input="Draft the release note.",
    extra_body={"thinking": {"type": "enabled"}},
    reasoning_effort="medium",
)

answer = next(
    part.text
    for item in resp.output if item.type == "message"
    for part in item.content if part.type == "output_text"
)
print(answer)

If you're weighing which interface to build on, we compared them for agents in Responses vs Assistants vs Chat Completions.

5. The one limit that will bite you: 384K output#

V4 Flash has a 1M-token context window, but its maximum output is 384K tokens — and in thinking mode the reasoning trace is spent from that same output budget. A long chain-of-thought plus a long answer can hit the ceiling and truncate the response mid-sentence. On any generation that can run long — a big refactor, a full document, a batch of tool calls — set max_tokens deliberately rather than trusting the default, and treat a finish_reason of length as a real error path, not a rare edge case. Our API errors, retries, and fallbacks how-to has the retry pattern.

The whole thing, in one line#

Change base_url and model, flip thinking on when the task needs it, read the answer from content (never reasoning_content), and cap max_tokens so the 384K ceiling can't swallow your output. That's a frontier-grade agent backend running against a budget-tier bill — which, as this week's Wire argued, is the default worth re-pricing your stack around this month.