DeepSeek — API Research (Phase 0)
Researched 2026-07-30 against official docs (api-docs.deepseek.com) and a live /models probe with a real key (/tmp/zyquo-probe/deepseek.json). Major change vs older integrations: deepseek-chat and deepseek-reasoner are RETIRED — only deepseek-v4-flash and deepseek-v4-pro exist now.
1. Base URL & Endpoints
Base: https://api.deepseek.com (OpenAI-compatible). An Anthropic-Messages-compatible surface also exists at https://api.deepseek.com/anthropic (not needed — Zyquo Cloud uses the OpenAI surface via OpenAICompatibleClient).
| Endpoint | Method | Purpose |
|---|---|---|
/chat/completions (also /v1/chat/completions) |
POST | Chat (streaming + non-streaming) |
/models |
GET | List models |
/user/balance |
GET | Account balance (nice-to-have for the usage footer) |
Docs: https://api-docs.deepseek.com/ and https://api-docs.deepseek.com/api/create-chat-completion
2. Authentication
Authorization: Bearer $DEEPSEEK_API_KEY. Keys from platform.deepseek.com.
3. Chat Model Catalog
Live probe (2026-07-30) returns exactly two models. Specs from https://api-docs.deepseek.com/quick_start/pricing. Both support streaming, vision — NO (text-only; unverified whether V4 added image input — docs do not document vision input; treat as text-only), tools/function calling (up to 128 functions), JSON mode (json_object), and thinking mode (default ON).
| Model ID | Context | Max output | $/1M input (cache hit) | $/1M input (cache miss) | $/1M output | Thinking | Concurrency |
|---|---|---|---|---|---|---|---|
deepseek-v4-flash |
1,000,000 | 384K | $0.0028 | $0.14 | $0.28 | ✅ default on (also non-thinking) | 2,500 |
deepseek-v4-pro |
1,000,000 | 384K | $0.003625 | $0.435 | $0.87 | ✅ default on (also non-thinking) | 500 |
Retired legacy IDs (do NOT ship in ModelCatalog): deepseek-chat and deepseek-reasoner were routing aliases (chat = non-thinking mode, reasoner = thinking mode of the current generation, latterly resolving to deepseek-v4-flash). They stopped resolving on 2026-07-24 15:59 UTC and now return errors (404-class). V4 launched in preview 2026-04-24, GA 2026-07-20. If migrating user configs: deepseek-chat → deepseek-v4-flash with thinking.type: "disabled"; deepseek-reasoner → deepseek-v4-flash with thinking enabled (note: reasoner mapped to Flash, not Pro). Sources: DeepSeek V4 migration, Developers Digest guide, TheRouter.ai (third-party corroboration of official release notes).
Max-output default vs maximum split is not documented beyond "384K max" — default max_tokens when omitted: unverified.
4. Request / Response Format
OpenAI-compatible with DeepSeek extensions/deviations (https://api-docs.deepseek.com/api/create-chat-completion):
model:"deepseek-v4-flash" | "deepseek-v4-pro"messages: rolessystem/user/assistant/tool; optionalnametemperature: 0–2, default 1;top_p: 0–1, default 1max_tokens: nullable int (input + output ≤ context)thinking:{ "type": "enabled" | "disabled" }— default enabled; plusreasoning_effort:"high" | "max"(defaults vary by request type; exact default unverified)stream,stream_options: {"include_usage": true}response_format:{"type": "text" | "json_object"}(nojson_schemadocumented)tools(≤128 functions),tool_choice,logprobs+top_logprobs(0–20),stop(≤16 sequences)- Deprecated/removed:
frequency_penaltyandpresence_penalty— "no longer supported". Do not surface these sliders for DeepSeek in the per-conversation parameters UI.
POST /chat/completions
{
"model": "deepseek-v4-flash",
"messages": [
{ "role": "system", "content": "You are a helpful assistant." },
{ "role": "user", "content": "Reply with exactly: OK" }
],
"thinking": { "type": "enabled" },
"reasoning_effort": "high",
"max_tokens": 4096,
"stream": false
}Response deviations from vanilla OpenAI:
choices[0].message.reasoning_content(nullable string): "For thinking mode only. The reasoning contents of the assistant message, before the final answer." → this feeds Zyquo Cloud's collapsible "Thinking…" section.finish_reasonvalues:stop,length,content_filter,tool_calls,insufficient_system_resource(DeepSeek-specific — surface as "DeepSeek servers overloaded").usage:prompt_tokens(=prompt_cache_hit_tokens+prompt_cache_miss_tokens),completion_tokens,total_tokens,prompt_cache_hit_tokens,prompt_cache_miss_tokens,completion_tokens_details.reasoning_tokens. Cost calc must use hit/miss split (cache-hit input is ~50× cheaper).
Vision: not documented for V4 — treat DeepSeek as text-only (no image_url support; unverified whether it errors or ignores).
Legacy V3-era rule ("do not pass reasoning_content back in the next request or the API errors") is unverified for V4 — the V4 docs no longer state it. Safe client behavior: never send reasoning_content back in messages (matches OpenAI-compat semantics either way). Whether temperature/top_p are ignored in thinking mode (as with the old reasoner): unverified for V4 — docs list them without model restrictions.
5. Streaming
Standard OpenAI SSE: data: {chunk} lines, terminated by data: [DONE]. DeepSeek specifics:
- Thinking mode streams
choices[0].delta.reasoning_contentfirst (while reasoning), thenchoices[0].delta.contentfor the final answer. The parser must watch both fields and switch the UI from the "Thinking…" section to the answer body whencontentstarts. - With
stream_options.include_usage: true, one extra chunk with fullusagearrives just before[DONE]. - Keep-alive under load (https://api-docs.deepseek.com/quick_start/rate_limit): non-streaming responses may pad with empty lines; streaming sends SSE comments
: keep-alive. The SSE parser must ignore comment lines and empty lines. If inference hasn't started after 10 minutes, the server closes the connection — use long read timeouts.
6. Special Parameters & Notes
thinking: {"type": "enabled"|"disabled"}— per-request toggle; default enabled on both models. Map Zyquo Cloud's "reasoning" toggle to this.reasoning_effort: "high" | "max"— extra thinking depth control (thinking mode).- Context caching is automatic (no opt-in): repeated prefixes hit the cache and bill at the cache-hit input rate; observable via
prompt_cache_hit_tokens/prompt_cache_miss_tokens. user_id(optional): scheduling isolation; on expanded-capacity accounts each distinctuser_idgets its own concurrency budget.- No
frequency_penalty/presence_penalty; nojson_schemaresponse format;nnot documented (unverified).
7. Rate Limits & Errors
(https://api-docs.deepseek.com/quick_start/rate_limit, https://api-docs.deepseek.com/quick_start/error_codes) DeepSeek uses concurrency limits, not RPM/TPM: 2,500 concurrent requests for v4-flash, 500 for v4-pro (a slot is held from send until the response completes). Exceeding → HTTP 429. Free capacity-expansion requests available. Under load, expect keep-alive padding (§5) rather than fast failures.
| HTTP | Meaning | Handling |
|---|---|---|
| 400 | Invalid request body format | fix request |
| 401 | Wrong API key | "Invalid API key for DeepSeek" |
| 402 | Insufficient balance (DeepSeek-specific) | tell user to top up |
| 422 | Invalid parameters | fix params per message |
| 429 | Concurrency limit | backoff + retry |
| 500 | Server error | retry with backoff |
| 503 | Server overloaded | retry after wait |
Error body: OpenAI-style {"error": {"message", "type", "code"}} — exact JSON shape not specified in official docs (unverified; confirm in Phase 7).
8. /models Listing
Yes. GET /models → minimal OpenAI shape (verified live): {"object":"list","data":[{"id":"deepseek-v4-flash","object":"model","owned_by":"deepseek"},{"id":"deepseek-v4-pro","object":"model","owned_by":"deepseek"}]}. IDs only — context/pricing/capabilities must come from the built-in catalog.