Fieldguide Fieldguide / DeepSeek V4.1 Flash / Module 2
Module 2 Getting Started Lesson 05 of 36 45 min Full lesson

Your First Call: Keys, Endpoints, SDK Compatibility

Make a request, understand every field you sent, and learn why no existing SDK needs to be rewritten.

Learning objectives

  • Create and store an API key without leaking it
  • Send a working request with both the OpenAI and Anthropic formats
  • Read a response object, including thinking blocks

Session agenda — 45 minutes

  • 5 minFraming — why this exists and what you will be able to do
  • 10 minCore concept — the idea, explained from first principles
  • 15 minWorked walkthrough — watch it happen, with the real fields and output
  • 10 minHands-on exercise — you run it and measure the result
  • 5 minCheckpoint — recall questions and a note to your future self

Why this lesson exists

DeepSeek deliberately made itself a drop-in replacement. That is excellent news and also the reason people skip learning the API — then spend an afternoon confused about a response field. This lesson is thirty minutes of setup followed by an hour of never being confused again.

Step one: a key, stored properly

Create your API key in the DeepSeek platform console. Then put it somewhere that is not your source code, not your shell history, and not a chat window.

Three storage rules that matter more than they sound:

  1. Environment variable or a secrets file with restrictive permissions. Read it at runtime. Never inline it in a script you might commit.
  2. One key per service. If a key is only used by one thing, revoking it costs you nothing and tells you exactly what broke.
  3. Never echo it. Not into a log, not into a screenshot, not into a chat with an assistant. The moment a secret appears in a transcript, its secrecy is gone — you cannot un-leak it by deleting the message.
# Store it once, with tight permissions
umask 077
echo 'DEEPS...EY=your-key-here' > ~/.deepseek.env
chmod 600 ~/.deepseek.env

# Load it in a shell session
set -a && source ~/.deepseek.env && set +a

Step two: the two base URLs

This is the whole "SDK compatibility" story, and it is two lines long.

FormatBase URLUse when
OpenAI-compatiblehttps://api.deepseek.comDefault. Any OpenAI SDK or tool works unchanged.
Anthropic-compatiblehttps://api.deepseek.com/anthropicYou already have Claude-format code, or a tool speaks the Anthropic API (Claude Code, some harnesses).

That is why no SDK needs rewriting. You are not adapting your code to DeepSeek — you are pointing an existing client at a different host. And note the practical consequence: it means most agent tools and coding assistants can use DeepSeek "for free," by config, without a plugin. That fact is the entire premise of Module 7.

Step three: the first request

curl https://api.deepseek.com/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $DEEPS...EY" \
  -d '{
    "model": "deepseek-flash",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "Explain prefix caching in two sentences."}
    ],
    "thinking": {"type": "enabled"},
    "reasoning_effort": "high",
    "stream": false
  }'

Every field here is worth knowing on sight.

FieldWhat it doesDefault
modelWhich model serves the requestRequired. Send deepseek-flash.
messagesThe full conversation arrayRequired. See the note below — this is not stateful.
thinking{"type":"enabled"} or disabledEnabled by default.
reasoning_effortlow / high / maxModel default. Lesson 9 covers choosing.
streamServer-sent events instead of one responsefalse. Use streaming for anything a human watches.

The API is stateless — this is the number one first-week confusion

The web chat remembers your conversation. The API does not. Every call must resend the entire message array. If you send one user message on turn two, the model has no idea what turn one was.

This sounds obvious written down and it is genuinely surprising the first time it bites. It is also the reason context engineering (Lesson 11) is a real discipline: you own the history, so you own the cost of it.

Reading the response

The shape is the same as any OpenAI-compatible response, with one addition that matters:

{
  "id": "...",
  "model": "deepseek-flash",
  "choices": [{
    "message": {
      "role": "assistant",
      "content": "Prefix caching stores ...",
      "reasoning_content": "The user wants two sentences. Key points: ..."
    },
    "finish_reason": "stop"
  }],
  "usage": {
    "prompt_tokens": 42,
    "completion_tokens": 118,
    "prompt_cache_hit_tokens": 0,
    "prompt_cache_miss_tokens": 42
  }
}

Three things to notice:

  • reasoning_content carries the thinking trace, separate from the answer. Read it whenever output surprises you — it is the best debugging tool you have, and it is free to read.
  • model echoes what actually served the request. This is your alias detector from Lesson 2.
  • The cache split in usage is the single most important field for your bill. Hit tokens and miss tokens are priced an order of magnitude apart. Lesson 6 is built on this.

Checkpoint

  1. What is the base URL for the Anthropic-format endpoint, and why would you use it?
  2. Why does an existing OpenAI SDK work without modification?
  3. What must you do differently on turn two of a conversation compared to the web chat?
  4. Which two usage fields predict your actual cost?
Answers
  1. https://api.deepseek.com/anthropic — for existing Claude-format code or tools that speak that API.
  2. DeepSeek implements an OpenAI-compatible API surface, so you only change the base URL.
  3. Resend the full message array. The API is stateless and holds no conversation history.
  4. prompt_cache_hit_tokens and prompt_cache_miss_tokens.

Exercise: three calls, three lessons

  1. Make a basic call. Send one message, non-streaming, and print the full response object. Confirm the model field says deepseek-flash.
  2. Read the thinking. Send a question that requires reasoning — something with a wrong-looking premise, or a small arithmetic puzzle. Print reasoning_content separately from content. Find the moment the model changes its mind, if there is one.
  3. Break it deliberately. Send a second call on the same topic with only the new user message and no history. Observe that it has amnesia. Then resend the full array. You have now felt the statelessness rather than just read about it.

Then make the same first call through the Anthropic-format endpoint with an Anthropic-style client. Both should produce equivalent output — that is the point.

Progress is stored in this browser only.
DeepSeek V4.1 Flash — The Practitioner Course Course syllabus · All courses