Setting up the DeepSeek API is not complicated in itself. What usually trips people up is three things: which platform the key belongs to, whether the Base URL is written in full, and whether the model name is the current version. Many "cannot connect" cases are not a model capability problem at all; the credentials and the endpoint simply do not match.
This article starts with registration, top-up, and key creation, then walks through the first curl and Python calls in order, before covering streaming output, thinking mode, max_tokens, and common errors. Follow it once and you should have the integration path working end to end.
Note: DeepSeek is a trademark of its owner. This article is not affiliated with DeepSeek. Model names, parameters, and limits may change between versions; this article uses the common form shown in the official documentation as of October 2026, and the official documentation and the on-site model pricing page take precedence.
1. Four things to separate before you start
Most API setup failures are not about model capability. They come from these four objects not being aligned:
| Object | Purpose | Most common mistake |
|---|---|---|
| Account | Determines the balance, billing, and ownership of the key | Using a key from platform A with the endpoint of platform B |
| API key | Identity credential | Copying it with spaces, line breaks, or quotes attached |
| Base URL | Where the request is sent | Omitting /v1, or mixing the official endpoint with a gateway endpoint |
| Model name | The model field in the request |
Reusing an outdated name from an old article |
The rule of thumb is simple: the key and the Base URL must come as a pair. An official key only works with the official endpoint, and a gateway key only works with the gateway endpoint. Mixing them usually returns 401 immediately.
2. Register, top up, and create a key
Using the official open platform as an example, the order is:
- Open the DeepSeek open platform, register, and sign in.
- Complete any required verification as prompted, then go to the top-up page.
- Top up a small amount first; run batch jobs only after the funds arrive.
- Go to the API Keys page, create a key, and name it clearly by purpose, for example
deepseek-testordeepseek-prod. - Copy the key and immediately save it to a password manager or a server-side environment variable; the page usually will not show the full value again after it closes.
- Create separate keys for testing and production, and set budget or usage alerts.
If you use ZSQH AI Gateway, the process is similar: create an account on the sign-up page, open the console to create a key and top up, then call it in the OpenAI-compatible way described below. Do not share one key between the two platforms. Otherwise, when something goes wrong, it is hard to tell whether the cause is balance, rate limiting, or a configuration error.
3. Base URL and model name: confirm before writing code
The OpenAI-compatible endpoint currently given in the official documentation is https://api.deepseek.com, with the chat completion path at /chat/completions. Some older tutorials use https://api.deepseek.com/v1; whether that works depends on what the official documentation currently says. If you are unsure, get the address from the official example working first.
| Item | Official direct | ZSQH AI Gateway |
|---|---|---|
| Base URL | https://api.deepseek.com |
https://ai.zhongshangqihang.com/v1 |
| Chat path | /chat/completions |
/v1/chat/completions |
| Key source | Official open platform | Gateway console |
| Model names | Per official documentation | Per on-site model pricing |
| Best for | DeepSeek only, with smooth official access and payment | A unified endpoint, multiple models, or RMB billing |
As of October 2026, the model names listed in the official documentation are deepseek-flash and deepseek-v4-pro. The older deepseek-chat and deepseek-reasoner names may no longer work. Do not fill in a model name from memory; check the official documentation or the on-site pricing page before calling.
4. Your first curl: get the smallest request working
Turn thinking off first to reduce variables. Official endpoint example:
export DEEPSEEK_API_KEY="sk-your-key"
curl "https://api.deepseek.com/chat/completions" \
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-flash",
"messages": [{"role": "user", "content": "Reply with OK only"}],
"thinking": {"type": "disabled"},
"max_tokens": 32
}'
A 200 response with content in choices[0].message.content means the key, Base URL, and model name are all correct. To use the gateway instead, replace the URL with https://ai.zhongshangqihang.com/v1/chat/completions and switch to a gateway key.
Note that thinking is a DeepSeek extension parameter, and not every OpenAI-compatible service supports it. If the gateway does not support it, remove the field or use the corresponding parameter described in the gateway documentation.
5. First Python call: use the OpenAI SDK
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com", # gateway: https://ai.zhongshangqihang.com/v1
)
resp = client.chat.completions.create(
model="deepseek-flash",
messages=[
{"role": "system", "content": "You are a concise technical assistant."},
{"role": "user", "content": "Explain what a vector database is in three sentences."},
],
max_tokens=512,
extra_body={"thinking": {"type": "disabled"}},
)
print(resp.choices[0].message.content)
print(resp.usage)
The OpenAI SDK does not recognize the thinking field, so it has to be passed through extra_body. Once the request works, look at usage first: how many tokens went to input and output, whether cache hits are reported, and whether reasoning content is counted separately. These numbers are more useful than a vague sense of speed when you later tune cost and timeout settings.
6. Streaming output and reasoning_content
Thinking is enabled by default, with a default effort of high. When it is on, the response includes reasoning_content alongside the final content. In a streamed response it is returned chunk by chunk in delta.reasoning_content.
stream = client.chat.completions.create(
model="deepseek-flash",
messages=[{"role": "user", "content": "Write a Python example that reads a CSV file"}],
stream=True,
max_tokens=4096,
reasoning_effort="high",
extra_body={"thinking": {"type": "enabled"}},
)
reasoning, answer = [], []
for chunk in stream:
if not chunk.choices:
continue
delta = chunk.choices[0].delta
if getattr(delta, "reasoning_content", None):
reasoning.append(delta.reasoning_content)
if delta.content:
answer.append(delta.content)
print("Reasoning: ", "".join(reasoning))
print("Final answer: ", "".join(answer))
In multi-turn conversations, if the request includes tools, the previous turn's reasoning_content must be sent back in full, or the API may return 400. Without tools, it can be omitted and the server will ignore it. For end users, collapse the reasoning content by default rather than showing all of it expanded.
7. How to configure max_tokens, temperature, and thinking
| Task | Thinking | Suggested starting point | Notes |
|---|---|---|---|
| Connectivity test | Off | max_tokens 32–128 | Only a short reply is needed |
| Classification, extraction | Off | 256–1024 | Structured output; reduce reasoning overhead |
| Customer support, writing | On | 1024–4096 | Adjust effort based on results |
| Code, complex reasoning | On | 4096 or more | Leave enough budget for reasoning |
The official documentation currently states: context length is 1M tokens, and max_tokens ranges from 1 to 384K. When unset, the default is 8K with thinking off and 64K with thinking on; with reasoning_effort set to max, the default is 128K. These values may change, so refer to the official documentation.
In thinking mode, temperature, presence_penalty, and frequency_penalty have no effect. Changing them does not raise an error, but it does not change the result either. Also, do not set max_tokens too low: reasoning content consumes the output budget, and a budget that is too small may cut the response off before the actual answer is written.
8. Troubleshooting 401, 402, 429, and timeouts
| Symptom | Common cause | What to do |
|---|---|---|
| 401 | Wrong key, missing Bearer, or key and Base URL from different platforms | Copy the key again, check the request headers, and confirm the endpoint matches |
| 402 | Insufficient account balance | Top up and retry; check the balance before changing code |
| 429 | Requests too fast, or concurrency or QPS limit exceeded | Reduce concurrency, use exponential backoff, split keys by project |
| 400/422 | Invalid parameter, model name, or context | Read the error message and check the model name and max_tokens |
| Timeout | Network, long output, or thinking time | Set connect and read timeouts separately, and limit output length |
| 500/503 | Upstream service error or overload | Wait briefly, then retry with backoff |
The 429 concurrency limit is counted per account, not divided evenly across keys. Multiple keys under the same account share the quota, so creating more keys does not get around the concurrency limit. The official documentation also notes that if inference has not started within 10 minutes, the connection is dropped; the client should recognize this case and retry.
9. Key security: at least five things before launch
- Store keys only in server-side environment variables or a secrets management service, never in front-end code, repositories, or logs.
- Use a separate key for testing, staging, and production, so problems can be traced and disabled quickly.
- Set balance alerts or spending limits to cap losses when usage looks abnormal.
- Log only a key prefix or fingerprint, never the full value.
- Rotate keys immediately when staff change or a leak is suspected, and review recent usage records.
10. Switching from official to a gateway: only two changes
When migrating, change base_url and api_key first, re-confirm model names on the gateway pricing page, and keep the rest of the request body as unchanged as possible. Compare output, latency, and usage with the same set of real prompts, observe for 3–7 days, and then move production over. Keep the official direct connection as a backup channel so you can roll back quickly if something goes wrong.
If you need a unified endpoint or multi-model billing, create a test key on ZSQH AI Gateway. Prices and available models are on the model pricing page.
Related reading:
- DeepSeek API Key Guide
- DeepSeek API Common Errors and Rate Limit Troubleshooting
- DeepSeek API Pricing and Billing
FAQ
Does the Base URL need a /v1 suffix?
Follow the example currently in the official documentation. The official OpenAI-compatible endpoint is written as https://api.deepseek.com, with the chat path at /chat/completions; gateways usually use a /v1 prefix. Do not guess from older tutorials. Run curl against the full address once to confirm.
Is a 401 a wrong key or a low balance?
401 means authentication failed. Check first whether the key is correct, whether it includes Bearer, and whether the key and Base URL belong to the same platform. An insufficient balance usually returns 402, so do not confuse the two.
Should thinking be enabled on the first call?
Keep it off initially and confirm the connection with the shortest possible request. Once the key, endpoint, and model name are confirmed, enable it as the task requires and start testing with a lower reasoning_effort.
What is a reasonable max_tokens value?
Start with a value that is sufficient for the task, then tighten it after the request works. Classification and extraction can start in the hundreds; long documents and code need a few thousand. Thinking mode needs budget for reasoning, and setting it too low can truncate the actual answer.
Can an official key be used with a gateway endpoint?
No. An official key corresponds only to the official endpoint, and a gateway key only to the gateway endpoint. Mixing them usually returns 401. When switching endpoints, change the key and the Base URL together.
