[Blog](https://excessionlabs.ai/blog/) · 2 November 2026 · Updated 3 November 2026 · [Excession Labs](https://excessionlabs.ai/about/)

# DeepSeek API guide: pricing, Python, streaming and tool calls

Source page: https://excessionlabs.ai/blog/deepseek-api-guide/

Call DeepSeek V4.1 Flash through the Excession API with your existing OpenAI-compatible client, from the first request to streaming, tool calls and error recovery.

On this page: [Choose a model and understand the price](#choose-a-model-and-understand-the-price) · [Create a key and add funds](#create-a-key-and-add-funds) · [Send your first request with curl](#send-your-first-request-with-curl) · [Use the OpenAI Python client](#use-the-openai-python-client) · [Stream a response](#stream-a-response) · [Complete a tool-call round trip](#complete-a-tool-call-round-trip) · [Choose the right endpoint](#choose-the-right-endpoint) · [Estimate cost and inspect usage](#estimate-cost-and-inspect-usage) · [Troubleshoot common errors](#troubleshoot-common-errors) · [Continue reading](#continue-reading)

## Choose a model and understand the price

The API base URL is `https://api.excessionlabs.ai/v1`. Use an Excession API key. Keys from other providers do not work.

| Model | API model ID | Input / 1M tokens | Cached input / 1M tokens | Output / 1M tokens |
| --- | --- | --- | --- | --- |
| DeepSeek V4.1 Flash | `deepseek/deepseek-v4.1-flash-1017` | $0.035 | $0.005 | $0.50 |
| DeepSeek V4.1 Flash Abliterated | `deepseek-v4.1-flash-abliterated` | $0.20 | $0.025 | $0.80 |

Prices are USD per million tokens. Output includes reasoning tokens. Cached input is a subset of total input and is not charged extra. Every payment option uses the same token prices. A plan adds plan credit, so each dollar you pay covers more tokens.

Regular DeepSeek is the default model. The abliterated variant is a separate model for authorized security work. To use it, set its exact model ID: changing a display label does not switch models. Both are listed in the [live model catalog](https://api.excessionlabs.ai/v1/models), with current prices and limits.

GLM 5.5, GLM 5.3 and Kimi K3.1 Pro are coming soon to the Excession API. They are not callable yet, and no API IDs, prices or launch dates are announced.

The catalog currently declares a 1,048,576-token context and a 131,072-token maximum output for these DeepSeek models. The gateway defaults to a 16,384-token output limit if you omit one. These are configured limits. They do not guarantee throughput or response time.

Conceptual illustration of the request and response path. The application uses an Excession key and selects a model; responses return through the API.

## Create a key and add funds

1. [Sign in and open API keys](https://excessionlabs.ai/login?next=%2Fapp%2Fkeys). Create a key and copy it when it is shown. Store it on your server or in an environment variable.
2. Every new account gets $0.50 API credit once, with no card required. Use it for your first requests; then [add funds in Billing](https://excessionlabs.ai/login?next=%2Fapp%2Fbilling%23add-funds) ($0.50 to $1,000 per top-up) or choose a monthly plan.
3. Send a small first request with an explicit maximum output. Review the result and its usage before increasing the budget.

A plan is optional. You can create a key before you add funds, but requests return HTTP 402 `insufficient_funds` until you add funds or choose a plan. Plan credit pays for API requests and for Incursion by Excession Labs, the terminal agent, so one Excession account covers both.

| Option | You pay | Plan credit or balance | Extra | Unused money |
| --- | --- | --- | --- | --- |
| Pay as you go | $0.50 to $1,000 per top-up | Same amount as balance | 0% | Never expires |
| Starter | $20/month | $30/month | +50% | Ends at renewal |
| Pro | $100/month | $175/month | +75% | Ends at renewal |
| Max | $200/month | $400/month | +100% | Ends at renewal |
| Ultra | $500/month | $1,250/month | +150% | Ends at renewal |

Balance never expires while your account is open, including after you cancel a plan. One plan covers one person.

Requests use plan credit first, then balance when permitted. With an active plan, you can turn off "Use balance after plan credit" to stop using balance. Without a plan, requests use your balance. See the [full pricing explanation](https://excessionlabs.ai/blog/simple-pricing/).

## Send your first request with curl

Set `EXCESSION_API_KEY` in your shell using your secret manager or a private environment file. Never include a real key in client-side JavaScript, a repository or a shared example.

```
curl --fail-with-body https://api.excessionlabs.ai/v1/chat/completions \
  -H "Authorization: Bearer $EXCESSION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek/deepseek-v4.1-flash-1017",
    "messages": [{"role": "user", "content": "Explain what an HTTP 401 status means."}],
    "max_tokens": 2048
  }'
```

For the abliterated variant, change only the `model` value to `deepseek-v4.1-flash-abliterated`. Keep the base URL and your Excession key.

## Use the OpenAI Python client

Install the SDK in your project environment with `python -m pip install openai`. Pin the version you validate in your application's dependency file. This example uses Chat Completions:

```
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["EXCESSION_API_KEY"],
    base_url="https://api.excessionlabs.ai/v1",
    timeout=120.0,
    max_retries=0,
)
model = "deepseek/deepseek-v4.1-flash-1017"

response = client.chat.completions.create(
    model=model,
    messages=[{"role": "user", "content": "Explain HTTP 401 in one paragraph."}],
    max_tokens=2048,
)
print(response.choices[0].message.content)
print(response.usage)
```

The explicit timeout and disabled retries make this example's behavior easy to inspect. Production retry behavior should depend on the error type and your request budget. Do not retry a 402 money error until you add funds or change the balance setting.

## Stream a response

Using the same `client` and `model`, set `stream=True`. Chat Completions delivers server-sent events. Not every chunk contains visible text; usage can arrive separately.

```
stream = client.chat.completions.create(
    model=model,
    messages=[{"role": "user", "content": "Explain how HTTP cache validation works."}],
    max_tokens=2048,
    stream=True,
    stream_options={"include_usage": True},
)
for chunk in stream:
    if chunk.choices:
        text = chunk.choices[0].delta.content
        if text:
            print(text, end="", flush=True)
    if chunk.usage is not None:
        print("\nUsage:", chunk.usage)
```

A stream can include reasoning or tool-call deltas as well as content. The simple display loop above prints visible content only. Do not treat an empty content delta as completion or assume that the first chunk contains the answer. If the connection ends unexpectedly, inspect your request log before resubmitting work that has side effects.

## Complete a tool-call round trip

The model requests a tool; your application validates and executes it, then sends the result back. The Excession API does not execute your application's functions. This deliberately small example provides only a trusted local lookup and limits the interaction to three model turns.

```
import json

messages = [{"role": "user", "content": "What does HTTP 401 mean? Use the lookup tool."}]
tools = [{
    "type": "function",
    "function": {
        "name": "lookup_http_status",
        "description": "Look up a supported HTTP status code.",
        "parameters": {
            "type": "object",
            "properties": {"code": {"type": "integer", "enum": [401, 403, 429]}},
            "required": ["code"],
            "additionalProperties": False,
        },
    },
}]
status_names = {401: "Unauthorized", 403: "Forbidden", 429: "Too Many Requests"}

for turn in range(3):
    response = client.chat.completions.create(
        model=model, messages=messages, tools=tools, max_tokens=2048,
    )
    message = response.choices[0].message
    if not message.tool_calls:
        print(message.content)
        break
    messages.append(message.model_dump(exclude_none=True))
    for call in message.tool_calls:
        if call.function.name != "lookup_http_status":
            raise ValueError("Unexpected tool name")
        args = json.loads(call.function.arguments)
        if not isinstance(args, dict) or set(args) != {"code"}:
            raise ValueError("Invalid tool arguments")
        code = args["code"]
        if type(code) is not int or code not in status_names:
            raise ValueError("Unsupported status code")
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": json.dumps({"code": code, "name": status_names[code]}),
        })
else:
    raise RuntimeError("Tool-call turn limit reached")
```

Keep the assistant message and each `tool_call_id` in the conversation. Validate arguments in your application even if you supply a schema. For tools that write files, send messages or change accounts, apply your own permission and retry rules before execution.

## Choose the right endpoint

| Endpoint | Request convention | Output-limit field |
| --- | --- | --- |
| `POST /v1/chat/completions` | OpenAI Chat Completions: `messages` | `max_tokens` or `max_completion_tokens` |
| `POST /v1/responses` | OpenAI Responses: `input` | `max_output_tokens` |
| `POST /v1/messages` | Anthropic Messages: `messages` | `max_tokens` |

The gateway exposes all three wire formats. Test the protocol and features your application uses with your selected model, because the gateway does not guarantee support for every SDK feature or model-specific option. The examples in this guide use Chat Completions. For an Anthropic SDK configuration, the base URL is `https://api.excessionlabs.ai` because that SDK adds `/v1/messages`.

## Estimate cost and inspect usage

Calculate the cost from uncached input, cached input and output separately:

```
cost_usd = ((input_tokens - cached_tokens) * input_price
          + cached_tokens * cached_price
          + output_tokens * output_price) / 1_000_000
```

Worked example: 1M input tokens, half of them cached, and 100,000 output tokens, at the prices in the table above. Token counts are in millions.

| Model | Uncached input | Cached input | Output | Total at token prices | Paid with Ultra plan credit (÷ 2.5) |
| --- | --- | --- | --- | --- | --- |
| DeepSeek V4.1 Flash | 0.5 × $0.035 = $0.0175 | 0.5 × $0.005 = $0.0025 | 0.1 × $0.50 = $0.0500 | $0.0700 | $0.0280 |
| DeepSeek V4.1 Flash Abliterated | 0.5 × $0.20 = $0.1000 | 0.5 × $0.025 = $0.0125 | 0.1 × $0.80 = $0.0800 | $0.1925 | $0.0770 |

These are arithmetic examples, not measured workloads or benchmarks. Cache hits depend on the serving model and request history, so a repeated prompt can still miss.

A plan gives more plan credit than you pay, so the same tokens cost you less. Ultra turns $500 into $1,250 of plan credit, which divides every token price by 2.5. This is the lowest effective price, and it holds only if you use the plan credit before it ends at renewal.

| Model | Input / 1M tokens | Cached input / 1M tokens | Output / 1M tokens |
| --- | --- | --- | --- |
| DeepSeek V4.1 Flash, effective with Ultra | $0.014 | $0.002 | $0.20 |
| DeepSeek V4.1 Flash Abliterated, effective with Ultra | $0.08 | $0.01 | $0.32 |

A request reserves estimated input plus its maximum output and settles against reported usage. The reservation can exceed the final cost. Lower `max_tokens` to reserve less. The [console](https://excessionlabs.ai/app) and authenticated `GET /v1/me` show plan credit, balance and the amount available now.

Successful non-streaming responses include `X-Cost-Usd`; streaming responses do not, so use Usage in the console for the cost of a streamed request. Served inference responses include `X-Request-Id`. Save the request ID alongside status and timing when troubleshooting. Do not log API keys or sensitive prompts.

## Troubleshoot common errors

| Status or symptom | What to check | Next action |
| --- | --- | --- |
| 400 `invalid_json` or `invalid_request` | JSON body and endpoint-specific input field | Send valid JSON with non-empty `messages`, or `input` for Responses. |
| 401 `invalid_api_key` | Missing, incorrect or revoked Excession key | Check your environment variable and create a replacement key if needed. |
| 402 `insufficient_funds` | Plan credit plus balance (`available_usd`) versus the request reservation (`required_usd`) | Add funds at the `billing_url` in the body, or lower maximum output. |
| 402 `balance_use_off` | Plan credit cannot cover the request, you have a balance, and balance use is off | Turn on "Use balance after plan credit" in Billing, or lower the request budget. |
| 429 `rate_limited` or `model_busy` | More than 600 requests per minute on one key, or the model is busy | Wait for `Retry-After` seconds and use bounded backoff. |
| 503 `model_unavailable`, `model_busy` or `service_unavailable` | The selected route is temporarily unavailable or at capacity. You are not charged. | Keep the error details; honor `Retry-After` when supplied, then retry later within your budget. |
| Empty visible output | Reasoning, tool calls or output budget | Inspect the complete message and finish reason before retrying. |

The configured per-key limit is 600 requests per minute. It caps request rate and commits to no throughput. For persistent failures, contact [support](mailto:support@excessionlabs.ai) with the request ID, model ID, endpoint and HTTP status.

## Continue reading

[Measured streaming sample and raw evidence](https://excessionlabs.ai/blog/deepseek-api-latency-sample/): ten requests from one client.

- [API model catalog and pricing](https://excessionlabs.ai/api)
- [Plan credit and balance](https://excessionlabs.ai/blog/simple-pricing/)
- [Docs](https://excessionlabs.ai/docs/): install Incursion, sign in from the terminal, and call the Excession API.
- [Acceptable Use Policy](https://excessionlabs.ai/aup/): use the Excession API and Incursion only for authorized work.
