Build a small Python program that sends a safe DeepSeek request, prints the final answer and exposes its completion state. The walkthrough keeps credentials in the environment and makes failure handling explicit.

What you'll build

The program asks for a short explanation of a database index, prints the returned text and then displays completion and usage information. It makes a single deliberate request and does not launch a retry loop. That shape is useful for establishing a baseline before you add files, streaming or tools.

The request uses DeepSeek’s documented OpenAI-compatible Chat Completions interface with a current model identifier. It explicitly selects non-thinking behavior for this introductory explanation. The provider’s quickstart and thinking guide describe the relevant configuration. Official DeepSeek documentation. Official DeepSeek documentation.

Treat the generated explanation as an example artifact to inspect. The tutorial does not claim that wording will be identical across runs or that the account has free inference. You will check that the response contains final text and that the completion state is visible. Those checks establish a useful integration baseline without confusing a successful connection with a completed application task.

Prerequisites

Follow DeepSeek API key setup and configure the credential for the account intended to own this experiment. Inspect the account’s billing readiness and review DeepSeek pricing before executing the request. Do not paste the key into the script or a shared command transcript.

Use a Python environment where you can install the compatible client. Keep this example in its own working directory so its dependency changes do not unexpectedly affect another application. Record the installed client version with your test notes after you establish a passing run. For a deployed service, reproduce that environment through your normal dependency process.

Choose a harmless first prompt and keep the task small. The example is about database indexing, so it does not require personal records, confidential documents or an account identifier. A later production test should use representative input with permission to send it and an explicit acceptance criterion. The safe baseline helps you separate configuration problems from workload-specific ones.

The script also checks for a missing DEEPSEEK_API_KEY before constructing a request. If it reports a missing setting, restore the variable through protected configuration and restart the process where needed. This additional local check is separate from the wrong-model API test below.

Install SDK

python -m pip install openai

Run the installation with the same Python interpreter that will execute the script. If your editor uses a different environment from the terminal, select the intended interpreter before debugging the API. A missing import is a local dependency issue; replacing a provider key cannot resolve it.

Set DEEPSEEK_API_KEY through your environment or secret manager. The script checks whether it is present without displaying it. If you use a local secret file through your own development tooling, exclude that file from version control and keep a separate example containing names rather than values. Restart a process that loads environment variables only at startup.

Full script

import os
import sys
from openai import OpenAI, APIConnectionError, APIStatusError

key = os.environ.get("DEEPSEEK_API_KEY", "").strip()
if not key:
    raise SystemExit("Set DEEPSEEK_API_KEY before running this script.")

model = "ai-api-hub-invalid-model" if "--bad-model" in sys.argv else "deepseek-flash"

client = OpenAI(api_key=key, base_url="https://api.deepseek.com",
                timeout=60.0, max_retries=0)
try:
    response = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content":
                   "Explain why a database index can speed up a lookup. "
                   "Use a short paragraph and mention a tradeoff."}],
        max_tokens=300,
        extra_body={"thinking": {"type": "disabled"}},
    )
except APIConnectionError:
    raise SystemExit("Connection failed. Check the network and try deliberately.")
except APIStatusError as exc:
    print(f"HTTP {exc.status_code}")
    print(exc.response.text)
    raise SystemExit(1)

if not response.choices:
    raise SystemExit("The response did not contain a completion choice.")
choice = response.choices[0]
answer = choice.message.content or ""
if not answer.strip():
    raise SystemExit("The response did not contain a final text answer.")
print("ANSWER")
print(answer)
print("FINISH_REASON", choice.finish_reason)
if response.usage:
    print("USAGE", response.usage.model_dump_json())
if choice.finish_reason == "length":
    print("The answer reached the configured output ceiling.", file=sys.stderr)
    raise SystemExit(2)

Save the script as deepseek_first_call.py and run it with the interpreter where you installed the client. The timeout and output ceiling are example application settings, not published provider limits. Adjust them for a real workload only after checking its latency and answer requirements.

The code disables automatic client retries so the introductory run has an obvious dispatch path. It handles connection failures separately from an HTTP rejection and prints the actual HTTP status and response body for the safe deliberate-error fixture. A production service can add a bounded retry policy for appropriate temporary failures after it has a clear task deadline and admission mechanism.

Expected output

ANSWER
<generated explanation of a database index>
FINISH_REASON stop
USAGE <the provider's reported usage JSON>

The labels above are literal output from the script; the answer and usage values vary. The example is a structural illustration, not evidence of a live request made from your account. Inspect whether the explanation answers the question and includes the requested tradeoff. Keep the final completion state with that assessment.

If the completion reaches the configured output ceiling, the script reports the condition and exits with a distinct result. Do not accept a partial artifact merely because text was returned. Decide whether to ask for a shorter answer, allow more output or change the task structure, then run a deliberate follow-up rather than silently looping.

For usage investigation, compare the returned fields with the official billing categories. If your task later relies on cache reuse, inspect the documented cache-hit and cache-miss fields instead of estimating them from repeated strings alone. Keep numeric usage in a safe test record; it is useful evidence for planning the real workload. Official DeepSeek documentation.

One deliberate error and its fix

python deepseek_first_call.py --bad-model

The branch sends ai-api-hub-invalid-model instead of the normal model identifier. Keep the credential configured so the request reaches model validation. The script exposes the returned rejection and stops; restore the ordinary command to use the supported model again.

The following error-field excerpt was captured on 2026-09-12 15:53 UTC from an authorized HTTP request to the same provider interface. It used harmless connection-validation input and small output settings. This records the provider’s rejection; it does not claim that the Python SDK example itself was executed.

These are normalized captured fields with the message preserved verbatim. They are not a reconstructed full provider response envelope. Empty fields and request identifiers are omitted.

{
  "http_status": 400,
  "code": "invalid_request_error",
  "type": "invalid_request_error",
  "message": "The supported API model names are deepseek-flash, deepseek-v4-pro, but you passed ai-api-hub-invalid-model."
}

Fix the deliberate error by restoring a current accessible model identifier. Do not resend the invalid identifier in a retry loop. If the ordinary request also fails, inspect that response independently because permission, funding and request validation can fail at different stages. Official error reference.

Keep the missing-key startup check as an additional local configuration guard. It tests whether the process can read its environment; it does not establish that the provider accepted the key or evaluated the requested model.

What this request costs

Interactive tool

Estimate your API costs

Your text and estimates stay in this browser. No API requests are sent to model providers.

Loading verified model records…

Use the AI API cost calculator with the model and actual workload assumptions, then compare the result with the usage reported by your request. The introductory script prints the provider’s usage; it does not query your balance or calculate an invoice. Keep conditional rates explicit when evaluating scheduled work.

When expanding the program, estimate the whole accepted task. A document workflow can require more input, a coding workflow can require correction turns, and a tool workflow can send additional context after a function returns. Include those calls in your plan rather than extrapolating from this short introductory explanation alone.

Next steps

Add one capability at a time. For structured records, follow the official JSON guide and validate required fields after parsing. For tools, preserve the documented conversation state and authorize each application action. For streaming, handle incremental output and final completion separately. Keep a passing non-streaming example while adding each feature. Official DeepSeek documentation. Official DeepSeek documentation.

Review DeepSeek model selection before changing identifiers and account concurrency before adding workers. Return to the DeepSeek API overview for current source links and service context. A useful next milestone is a representative task that your application can validate, account for and recover when it does not complete.

Frequently asked questions

Why use the OpenAI package for a DeepSeek request?
DeepSeek documents a compatible interface. The script still uses the DeepSeek endpoint and credential; the client package does not determine which account is billed.
Will the output text match the example exactly?
No. The displayed shape identifies the script’s labels. Generated wording and reported usage can vary between requests.
Why are automatic retries disabled?
The introductory run has an explicit request path. Add a bounded policy later after classifying failures and defining the task deadline.
What does the wrong-model exercise verify?
It sends a deliberately invalid model identifier and checks that the actual provider rejection is exposed clearly. A missing-key check remains a separate local setup check.
What should I do with a truncated answer?
Treat it as incomplete. Reconsider the requested answer shape or configured output ceiling, then make a deliberate follow-up.
Can I paste the full response into a public issue?
Review it first. Share only the safe fields and harmless reproducer needed for diagnosis, excluding secrets and private input or output.

Sources

Last verified · Source ↗