Four wire formats
DeepSeek exposes the same two models –
deepseek-flash and deepseek-v4-pro – through
four different request shapes, so that existing ecosystems can point at it
without code changes. They are not interchangeable.
Which one to use
| Format | Path | Reach for it when |
|---|---|---|
OpenAI chatds chat | /chat/completions | Default. Widest tool support, and the only format with chat prefix completion. |
Anthropic Messagesds anthropic | /anthropic/v1/messages | The surrounding tooling speaks Anthropic – Claude Code, the Anthropic SDKs, the Claude desktop app. |
OpenAI Responsesds respond | /responses | You need JSON Schema output. Also what Codex speaks. (Its server-side web search was removed upstream on 2026-09-10.) |
FIMds fim | /beta/completions | Fill-in-the-middle code completion. No chat structure at all. |
What actually differs
| chat | anthropic | respond | fim | |
|---|---|---|---|---|
| Auth header | Bearer | x-api-key | Bearer | Bearer |
max_tokens | optional | required | optional | optional |
| Thinking toggle | thinking.type | thinking.type | reasoning.effort: none | never thinks |
| Effort control | reasoning_effort | output_config.effort | reasoning.effort | – |
| JSON Schema output | – | – | yes | – |
| Server-side web search | – | – | removed 2026-09-10 | – |
| Prefix completion | yes (beta path) | – | – | – |
| Models | both | both | both | both |
| Stream terminator | data: [DONE] | message_stop | response.completed | data: [DONE] |
The token-accounting trap
This is the one that silently corrupts cost tracking, and it is not stated
in the published docs. The formats disagree about what
input_tokens means.
The same prompt, sent both ways. /chat/completions reported
prompt_tokens: 289. /anthropic/v1/messages reported
input_tokens: 33 with
cache_read_input_tokens: 256.
33 + 256 = 289. On the Anthropic endpoint,
input_tokens excludes cache reads. On the OpenAI chat and
Responses endpoints, the input count includes them.
| Format | Full prompt is | Cached portion |
|---|---|---|
| chat | prompt_tokens | prompt_cache_hit_tokens |
| anthropic | input_tokens + cache_read_input_tokens | cache_read_input_tokens |
| respond | input_tokens | input_tokens_details.cached_tokens |
Get it backwards and a heavily-cached Anthropic call looks 8× cheaper
than it was. deepseek-cli normalises all three into one shape
before pricing anything, and
pins the
difference in tests using those exact numbers.
Claude model names
The Anthropic endpoint accepts Claude model names and remaps them server-side, which is what lets tools with hard-coded model lists work:
| You send | You get |
|---|---|
claude-opus-* | deepseek-v4-pro |
claude-sonnet-*, claude-haiku-* | deepseek-flash |
| anything unrecognised | deepseek-flash |
Because billing follows the model that actually ran, the usage line prints both names:
$ ds anthropic "hello" --model claude-opus-4-1
· claude-opus-4-1→pro · 10 in · 8 out · ~$0.000011 · 0.9s
The reasoning round-trip
In thinking mode the chain of thought comes back alongside the answer. What you do with it on the next turn is not optional:
- If the request carried
tools, every assistant message'sreasoning_contentmust be sent back on every later request. Omit it and the API answers400. - If it did not, the field is ignored server-side – so replaying it spends input tokens on text the model discards.
Sessions in this CLI keep the reasoning stored either way, and decide per request whether to put it on the wire.
Shared limits
- Images on flash only. Since 2026-09-10
deepseek-flashtakes images through chat completions and Responses;deepseek-v4-prois text only. - Thinking is on by default, and what its template costs
depends on
--effort: on V4 flash it was +79 input tokens at the default, +92 atmax, and nothing at all atlow– where the model still reasons. V4.1 Flash has not been re-measured. The measured table. - Slow starts are normal. The API holds the connection with
: keep-alivecomments for up to ten minutes before inference begins under load. - One error envelope across all four:
{"error":{"message","type","param","code"}}.