Live test: July 25, 2026 | Official endpoint | Three privacy-safe requests | All monetary values redacted
The DeepSeek API balance endpoint is GET https://api.deepseek.com/user/balance. Send a DeepSeek API key in the Bearer Authorization header, and the response tells you whether the account currently has sufficient balance for API calls and how its balance is divided between granted and topped-up funds.
We tested the endpoint live with three sequential requests: no credential, a synthetic invalid credential, and an authorized temporary credential held in memory. The responses were HTTP 401, 401, and 200, exactly as preregistered. The authorized response reported is_available: true and one USD balance row. Every monetary value was replaced in memory with [REDACTED_MONETARY_VALUE] before any result was saved. This article never states, estimates, hashes, rounds, or infers the private amount.
This is an independent technical test. Chat-Deep.ai is not the official DeepSeek Platform or billing portal. If you still need general setup, start with our published DeepSeek API guide.
Key takeaways
- Use
GET /user/balancefrom a trusted backend with Bearer authentication. is_availablemeans balance sufficiency, not service uptime or guaranteed job completion.- Treat
balance_infosas an array and keep USD and CNY amounts separate. - Parse the three amount fields as exact decimal strings, never approximate binary floats.
- The endpoint is not a price calculator, transaction ledger, per-key usage report, or grant-expiration API.
- Never expose the API key or raw balance in browser code, logs, screenshots, CI artifacts, or support tickets.
Quick answer: how to check DeepSeek API balance

The official Get User Balance reference documents this request:
curl --silent --show-error --fail-with-body \
"https://api.deepseek.com/user/balance" \
-H "Accept: application/json" \
-H "Authorization: Bearer $DEEPSEEK_API_KEY"
The DeepSeek API introduction defines HTTP Bearer authentication. Keep the key in an environment variable or secret manager, and make the call server-side.
A successful response has this shape. The values below reproduce our sanitized live structure, not fictional money:
{
"is_available": true,
"balance_infos": [
{
"currency": "USD",
"total_balance": "[REDACTED_MONETARY_VALUE]",
"granted_balance": "[REDACTED_MONETARY_VALUE]",
"topped_up_balance": "[REDACTED_MONETARY_VALUE]"
}
]
}
is_available is the current funding signal. total_balance includes the unexpired granted balance and topped-up balance. The amounts are strings, not JSON numbers. The schema lists USD and CNY as possible currencies, but it does not promise that every account returns both.
How we tested GET /user/balance

The benchmark ran from 2026-07-25T19:10:26.365Z through 2026-07-25T19:10:27.388Z. It sent three GET requests sequentially with concurrency one, one attempt per call, a 30-second timeout, and no retries:
- No Authorization header.
- A fixed synthetic invalid Bearer value that was not API-key-shaped.
- An authorized credential provided to the runner in process memory.
The purpose was to verify authentication behavior and the successful response structure without retaining private financial data.
| Call | Authentication | Expected | Observed | Check result |
|---|---|---|---|---|
| Unauthorized GET | Header omitted | 401 | 401 | 4 / 4 |
| Invalid-auth GET | Synthetic invalid Bearer value | 401 | 401 | 4 / 4 |
| Authorized GET | Temporary key in memory | 200 | 200 | 8 / 8 |
| Total | 401, 401, 200 | 16 / 16 |
All three calls passed every predefined check. That is 3 / 3 call-level passes and 16 / 16 individual checks. It is a contract-test result, not an accuracy score or uptime percentage.
The authorized body:
- Parsed as a JSON object.
- Contained
is_availableas a boolean. - Contained
balance_infosas an array. - Reported
is_available: true. - Contained one balance entry with currency
USD. - Contained all three documented monetary fields as strings.
- Contained no unrecognized top-level or balance-entry fields.
- Had every amount replaced with the fixed redaction token before persistence.
The missing-auth response returned 401 without a retained JSON error object. The synthetic-invalid-auth response returned 401 with a JSON error object whose conventional field names and types were retained, but whose messages and values were discarded. Those are dated observations, not permanent error-body guarantees.
Exact timing definitions and results
The runner deliberately avoided the vague label “latency.” It recorded:
response_headers_ms: elapsed from request start untilfetchresolved with response headers.full_body_ms: elapsed from request start until the complete body was read into memory. Structural redaction followed immediately, but its processing time was not included in this measurement.body_read_after_headers_ms: the difference between those two measurements.
| Call | response_headers_ms | full_body_ms | body_read_after_headers_ms |
|---|---|---|---|
| Header omitted, HTTP 401 | 427.070 | 427.647 | 0.577 |
| Synthetic invalid Bearer, HTTP 401 | 317.090 | 317.249 | 0.158 |
| Authorized, HTTP 200 | 274.877 | 275.045 | 0.168 |
No response-header values, cookies, raw response body, raw-response hash, account identifier, billing detail, or amount was persisted. These timings describe one client session and observation point. They are not a service-level benchmark, billing-system performance guarantee, or model-response timing test.
What the balance endpoint does and does not tell you

Many account questions sound similar but require different data sources:
| Question | Correct source | What it answers |
|---|---|---|
| Does the account currently report usable API funds? | GET /user/balance | Funding sufficiency and balance composition |
| What do current models cost? | DeepSeek API pricing | Current input, output, and cache rates |
| How many tokens did one completion use? | The completion response usage object | Request-level token accounting |
| Which API key generated historical usage? | Platform Usage export | Monthly usage detail broken down by key |
| When does a grant expire? | Platform Billing page | Grant-expiration information |
| Is there a platform incident? | Official DeepSeek status | Service incident information |
| Which models are currently listed? | Official model documentation or /models | Model catalog, not funding |
The balance endpoint returns no transaction history, top-up record, invoice, refund state, grant-expiration date, token estimate, usage-by-key field, timestamp, or price table. It cannot predict how many future requests the account can fund.
DeepSeek balance response fields explained

is_available
DeepSeek defines this boolean as whether the user’s balance is sufficient for API calls. In our authorized test it was true.
That does not guarantee that a large batch, agent loop, or long-context request will finish. The snapshot can become stale immediately, concurrent workers can spend funds, and a request can independently fail authentication, validation, rate limiting, policy checks, or service availability.
balance_infos
This field is an array, not one guaranteed object. Iterate every returned entry and validate its shape. Our test returned one row, but that single-account observation does not establish a universal row count or ordering.
currency
The official schema lists USD and CNY as possible values. Our live row was USD. Do not assume that both currencies will appear, infer zero from an absent currency, or add USD and CNY balances together. Cross-currency reporting needs an explicit conversion source and policy outside this endpoint.
total_balance
The documentation defines this as the total available balance, including granted and topped-up funds. It is returned as a string.
granted_balance
This is the total granted balance that has not expired. The endpoint does not return individual grants or expiration dates. DeepSeek’s official FAQ directs users to the Billing page for granted-balance expiration.
topped_up_balance
This is the topped-up balance. The FAQ says topped-up balance does not expire. DeepSeek’s Models and Pricing page says fees are deducted from granted or topped-up balance, with granted balance preferred when both are available.
Why the amounts must remain decimals
All three money fields are strings in the official schema. The example in the documentation uses two decimal places, but the contract does not publish a fixed scale or rounding rule. Parse them with an exact decimal type. Binary floating-point comparisons can drift around alert thresholds.
Safe cURL usage
The basic cURL command prints the private response. That may be acceptable in a secured local terminal, but it is unsafe for a screenshot, shared shell transcript, or CI log. Do not use curl -v; verbose output can expose request headers.
For a sanitized structural view with jq, replace monetary fields before they reach terminal output:
curl --silent --show-error --fail-with-body \
"https://api.deepseek.com/user/balance" \
-H "Accept: application/json" \
-H "Authorization: Bearer $DEEPSEEK_API_KEY" |
jq '{
is_available,
balance_infos: [
.balance_infos[] | {
currency,
total_balance: "[REDACTED_MONETARY_VALUE]",
granted_balance: "[REDACTED_MONETARY_VALUE]",
topped_up_balance: "[REDACTED_MONETARY_VALUE]"
}
]
}'
This projection still reveals the funding boolean and currencies. Remove those too when they are not required. Never paste the literal key into the command because shell history, process inspection, and recordings can retain it. Our DeepSeek API key security guide covers creation and safer storage.
Python balance checker with Decimal
This example parses monetary strings with Decimal, validates every row, and returns a typed internal result. It prints only readiness and currency labels:
import json
import os
from dataclasses import dataclass
from datetime import datetime, timezone
from decimal import Decimal, InvalidOperation
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen
ENDPOINT = "https://api.deepseek.com/user/balance"
ALLOWED_CURRENCIES = {"USD", "CNY"}
@dataclass(frozen=True)
class BalanceRow:
currency: str
total: Decimal
granted: Decimal
topped_up: Decimal
@dataclass(frozen=True)
class BalanceSnapshot:
is_available: bool
rows: tuple[BalanceRow, ...]
checked_at: datetime
def read_deepseek_balance() -> BalanceSnapshot:
request = Request(
ENDPOINT,
method="GET",
headers={
"Accept": "application/json",
"Authorization": f"Bearer {os.environ['DEEPSEEK_API_KEY']}",
},
)
try:
with urlopen(request, timeout=10) as response:
payload = json.load(response)
except HTTPError as error:
# Never log the response body or Authorization header here.
if error.code == 401:
raise RuntimeError("DeepSeek authentication failed") from None
if error.code == 402:
raise RuntimeError("DeepSeek reports insufficient balance") from None
if error.code == 429:
raise RuntimeError("DeepSeek rate limit reached") from None
raise RuntimeError(f"DeepSeek returned HTTP {error.code}") from None
except URLError:
raise RuntimeError("DeepSeek balance state is unknown") from None
if not isinstance(payload, dict):
raise ValueError("Expected a JSON object")
if not isinstance(payload.get("is_available"), bool):
raise ValueError("Expected is_available to be boolean")
if not isinstance(payload.get("balance_infos"), list):
raise ValueError("Expected balance_infos to be an array")
rows = []
for item in payload["balance_infos"]:
if not isinstance(item, dict):
raise ValueError("Expected each balance entry to be an object")
currency = item.get("currency")
if currency not in ALLOWED_CURRENCIES:
raise ValueError("Unexpected or missing currency")
try:
values = [
item["total_balance"],
item["granted_balance"],
item["topped_up_balance"],
]
if not all(isinstance(value, str) for value in values):
raise ValueError("Balance amounts must be strings")
total, granted, topped_up = map(Decimal, values)
except (KeyError, InvalidOperation):
raise ValueError("Invalid balance field") from None
rows.append(BalanceRow(currency, total, granted, topped_up))
return BalanceSnapshot(
is_available=payload["is_available"],
rows=tuple(rows),
checked_at=datetime.now(timezone.utc),
)
snapshot = read_deepseek_balance()
print({
"ready": snapshot.is_available,
"currencies": [row.currency for row in snapshot.rows],
"checked_at": snapshot.checked_at.isoformat(),
})
In production, even the ready value and currencies may be restricted operations data. Do not print snapshot.rows, and never serialize the object into broad application logs.
Node.js balance checker
JavaScript has no built-in decimal-money type. This minimal Node.js example validates and preserves amount strings without arithmetic:
const endpoint = "https://api.deepseek.com/user/balance";
const allowedCurrencies = new Set(["USD", "CNY"]);
async function readDeepSeekBalance() {
const response = await fetch(endpoint, {
method: "GET",
headers: {
Accept: "application/json",
Authorization: `Bearer ${process.env.DEEPSEEK_API_KEY}`,
},
signal: AbortSignal.timeout(10_000),
});
if (!response.ok) {
// Do not log response headers, body, or the request configuration.
const labels = {
401: "authentication_failed",
402: "insufficient_balance",
429: "rate_limited",
500: "server_error",
503: "service_overloaded",
};
throw new Error(labels[response.status] || `http_${response.status}`);
}
const payload = await response.json();
if (
typeof payload !== "object" ||
payload === null ||
typeof payload.is_available !== "boolean" ||
!Array.isArray(payload.balance_infos)
) {
throw new Error("invalid_balance_response");
}
const rows = payload.balance_infos.map((item) => {
if (
typeof item !== "object" ||
item === null ||
!allowedCurrencies.has(item.currency)
) {
throw new Error("invalid_balance_entry");
}
for (const field of [
"total_balance",
"granted_balance",
"topped_up_balance",
]) {
if (typeof item[field] !== "string") {
throw new Error("invalid_balance_amount");
}
}
return {
currency: item.currency,
total: item.total_balance,
granted: item.granted_balance,
toppedUp: item.topped_up_balance,
};
});
return {
isAvailable: payload.is_available,
rows,
checkedAt: new Date().toISOString(),
};
}
const snapshot = await readDeepSeekBalance();
console.log({
ready: snapshot.isAvailable,
currencies: snapshot.rows.map((row) => row.currency),
checkedAt: snapshot.checkedAt,
});
Use this on a backend, not in frontend JavaScript. If thresholds require arithmetic, use a reviewed decimal library and keep currency-specific policies separate.
PowerShell balance check for Windows
Set DEEPSEEK_API_KEY through a protected process or secret-injection workflow rather than typing the literal key into recorded shell history. This example builds the Authorization header in memory and prints only a sanitized projection:
if ([string]::IsNullOrWhiteSpace($env:DEEPSEEK_API_KEY)) {
throw "DEEPSEEK_API_KEY is not set"
}
$headers = @{
Accept = "application/json"
Authorization = "Bearer $($env:DEEPSEEK_API_KEY)"
}
$response = Invoke-RestMethod `
-Method Get `
-Uri "https://api.deepseek.com/user/balance" `
-Headers $headers `
-TimeoutSec 10
if ($response.is_available -isnot [bool]) {
throw "Expected is_available to be boolean"
}
$safeView = [pscustomobject]@{
is_available = $response.is_available
balance_infos = @(
$response.balance_infos | ForEach-Object {
[pscustomobject]@{
currency = $_.currency
total_balance = "[REDACTED_MONETARY_VALUE]"
granted_balance = "[REDACTED_MONETARY_VALUE]"
topped_up_balance = "[REDACTED_MONETARY_VALUE]"
}
}
)
}
$safeView | ConvertTo-Json -Depth 5
Remove-Variable response, headers
The raw response still exists briefly in process memory, so do not enable transcript logging or print $response. If a request fails, record a sanitized status category rather than dumping the exception, request headers, or response body.
Production preflight and low-balance monitoring

The official documentation does not publish a polling interval for this endpoint. Calling it before every completion can add unnecessary dependency traffic and still cannot eliminate a race between the check and subsequent spend.
A safer design keeps a short-lived, application-defined snapshot:
cached snapshot
-> fresh and available: admit work under local budget policy
-> fresh and unavailable: defer discretionary paid work
-> stale: refresh once through a shared worker
-> refresh failed: mark balance unknown, then apply fail-open/closed policy
Use three explicit states:
- Available: the last authenticated HTTP 200 returned
is_available: true. - Unavailable: the last authenticated HTTP 200 returned
is_available: false. - Unknown: no recent valid snapshot, schema failure, timeout, 401, or server error.
Do not map unknown to zero balance. A credential outage and a funding outage require different remediation.
Monitoring pattern
- Fetch through one backend worker rather than every application instance.
- Record UTC check time and last-success time.
- Cache for a conservative interval chosen from your operational needs; it is not a DeepSeek limit.
- Keep exact amounts in a restricted store only if threshold alerts require them.
- Evaluate thresholds per currency with exact decimals.
- Emit low-cardinality states such as
available,unavailable,stale, andauth_failed. - Alert when the last successful snapshot becomes too old.
- Recheck after HTTP 402 instead of retrying the same paid request.
- Reconcile actual completion
usagefields with the current price table. - Protect monitoring dashboards because balances reveal financial operations.
Several concurrent workers can all pass the same snapshot and then spend simultaneously. For large jobs, reserve an internal budget before admission, cap output, bound retries and agent steps, and update the reservation with actual token usage. The endpoint itself provides no reservation or atomic budget-control operation.
Whether an unknown state should fail open or closed is an application decision. A noncritical batch can wait; an essential workflow may continue under a tightly bounded local budget. DeepSeek does not prescribe that policy.
Why is_available true is not a budget forecast
Our live true result means the tested account reported sufficient balance at that moment. It says nothing about the private amount or how long it will last.
Future spend depends on the selected model, input length, output length, cache-hit versus cache-miss input, retries, concurrent traffic, tool loops, and price changes. A long job can cost more than expected even though the preflight snapshot is available.
Use the balance endpoint for current funding state. Use token estimates before admission, the response usage object after each DeepSeek Chat Completions API call, and the current DeepSeek API pricing for cost calculation. Keep a margin for uncertainty; do not convert is_available into an unsupported request-count estimate.
Fix 401, 402, 429, and service errors

DeepSeek’s official Error Codes page defines the following platform-wide meanings. The balance reference itself publishes only its HTTP 200 success schema, so do not assume every global code has an endpoint-specific error shape.
| Status | Official meaning | Safe response |
|---|---|---|
| 401 | Authentication fails | Check the key source, revocation, whitespace, environment, and Bearer header without logging the key |
| 402 | Insufficient balance | Stop unchanged retries, check balance and official Billing or Top Up, then retry a small bounded request after funding is available |
| 429 | Rate limit reached | Pace requests; do not diagnose this as a funding problem |
| 500 | Server error | Retry with bounded backoff; contact support if it persists |
| 503 | Server overloaded | Retry after a brief wait with bounded backoff |
Our no-credential and synthetic-invalid-credential controls both returned 401. Do not use their bodies as a permanent parser contract: one was not retained as valid JSON, while the other was a JSON error object.
For 401, verify that the process loaded the intended environment, the key has not been revoked, and the header is exactly Authorization: Bearer <key>. Our API key guide covers secure setup.
For 402, do not blindly retry. Check current balance, resolve funding through the official Platform if appropriate, and retry only after the account reports availability. We did not create a 402 test because intentionally draining or changing an account would be destructive.
HTTP 429 is a capacity signal, not a credit signal. See the published DeepSeek API rate limits guide for separate handling.
If a top-up appears under the wrong account or does not match expectations, the official FAQ advises confirming the currently logged-in account, checking whether historical payments belong to another login identity, and using the official support route for account-specific discrepancies.
Balance, Billing, Usage, Top Up, and pricing
GET /user/balance is only one part of account management:
- Balance endpoint: current funding sufficiency and balance composition.
- Billing: grant-expiration details, refunds, and account billing context.
- Usage: monthly export; the FAQ says the CSV named
amountcontains usage broken down by API key. - Top Up: add funds using the payment options currently shown by the official Platform.
- Pricing: current per-token rates and deduction rules.
The FAQ says topped-up balance does not expire, while granted-balance expiration is shown in Billing. It also says unused balances are refundable through the Billing refund workflow. The Open Platform Terms add that refunds are reviewed, may deduct necessary costs, cover the remaining unspent amount in one lump sum, do not support partial refunds, and do not refund spent amounts.
DeepSeek’s pricing page says granted balance is preferred when both granted and topped-up funds are available. Prices can change, so use our pricing guide for the focused cost discussion and verify the live official rate before budgeting.
Use the official DeepSeek links guide to avoid unofficial billing or top-up pages.
API-key and screenshot security

The Open Platform Terms say the API key is a necessary credential, must be kept secure, must not be shared or publicly disclosed, and must not be exposed in browser or client-side code. They also place responsibility for fees and losses caused by key leakage on the developer.
For a balance integration:
- Use a backend secret manager and least-privilege operations access.
- Never send the key or raw response to a browser.
- Do not use verbose HTTP output in screenshots.
- Redact before persistence, not after uploading.
- Use opaque masks rather than blur or pixelation.
- Exclude account email, avatar, IDs, transactions, tabs, notifications, and browser profiles.
- Remove image metadata and inspect the final pixels at full zoom.
- Revoke temporary test keys after use.
- Search the artifact folder for key-shaped strings before publication.
Our saved benchmark retained only allowlisted structure: statuses, precise timings, is_available, USD/CNY labels, field names and types, unknown-field counts, and check outcomes. It retained no raw body, headers, cookies, response hash, account identifier, billing detail, or monetary value.
Limitations of this live test
This was one account, one endpoint, one network path, and one short window on July 25, 2026. The authorized evidence is one response, not a longitudinal reliability study.
We did not induce HTTP 402, change the balance, top up, refund, inspect billing history, study polling limits, compare accounts, or test multiple currencies. The one observed USD row does not mean every account returns USD or exactly one row. The availability flag can change after any check.
The privacy design intentionally prevents amount arithmetic, equality checks, balance-change measurement, or cost reconciliation from this evidence package. Authentication and response shapes can change. A successful balance check does not prove a model request will succeed or the platform is incident-free.
Frequently asked questions
How do I check my DeepSeek API balance?
Send an authenticated GET request to https://api.deepseek.com/user/balance with your DeepSeek API key in the Bearer Authorization header.
What is the DeepSeek API balance endpoint?
The documented endpoint is GET /user/balance on the official https://api.deepseek.com base URL.
What does is_available mean in the DeepSeek balance response?
DeepSeek defines it as whether the user’s balance is sufficient for API calls. It is a current funding signal, not a promise that a large queued workload will finish.
What is the difference between total, granted, and topped-up balance?
total_balance is the total available amount, granted_balance is unexpired granted credit, and topped_up_balance is the amount added through top-ups.
Can the DeepSeek balance response include USD and CNY?
The official schema lists USD and CNY as possible currencies. Code should iterate balance_infos and avoid adding different currencies without an explicit conversion policy.
Why are DeepSeek balance amounts returned as strings?
The official JSON schema represents each amount as a string. Keep exact decimal semantics and use decimal-aware arithmetic for comparisons and alerts.
Is DeepSeek API balance tracked separately for each API key?
The endpoint is documented as the user’s account balance, not a per-key ledger. DeepSeek’s FAQ directs users to a Usage export for detailed usage broken down by API key.
Does /user/balance show usage or predict my next request cost?
No. Use request usage data, token estimates, and current model pricing to estimate spend. The balance endpoint only reports current account funding information.
Do DeepSeek API credits expire?
DeepSeek’s current FAQ says topped-up balance does not expire and that granted-balance expiration can be checked on the Billing page. Verify the current policy before relying on it.
How do I fix a DeepSeek API 401 error?
Check that the key is valid, loaded from the intended environment, not revoked, and sent as Authorization: Bearer <key>. Do not expose the key while debugging.
How do I fix a DeepSeek API 402 insufficient balance error?
Stop retrying the unchanged paid request, check /user/balance, open the official Billing or Top Up page if needed, and retry a small request only after funding is available.
Does is_available: true guarantee my batch or agent will finish?
No. Balance can change after the check, concurrent workers can spend it, and actual cost depends on tokens, retries, model pricing, and cache behavior.
How often should I poll the DeepSeek balance endpoint?
DeepSeek does not publish a dedicated polling interval for this endpoint. Cache results and choose a conservative interval based on operational need rather than calling it before every completion.
Can I call the balance endpoint from frontend JavaScript?
Do not expose a DeepSeek API key in browser or client-side code. Call the endpoint from a trusted backend and return only the minimum status your interface needs.
Does DeepSeek is_available show whether the API service is online?
No. It concerns account balance sufficiency. Use the official service-status page for incidents and the current model documentation or /models for model availability.
Official sources and test evidence
Product facts were checked against first-party DeepSeek sources on July 25, 2026:
- Get User Balance – method, path, response fields, types, and currencies.
- DeepSeek API Introduction – Bearer authentication.
- Error Codes – global 401, 402, 429, 500, and 503 meanings.
- Models and Pricing – deduction rules and current pricing context.
- Token and Token Usage – request usage and token-billing context.
- DeepSeek FAQ – expiration, refunds, top-up, and per-key usage export.
- Open Platform Terms – key security, payment, refund, and availability terms.
- DeepSeek Status – service incidents.
The sanitized test package contains a preregistered call plan, transformed JSON results, a flattened CSV, methodology, and verification checks. It contains no API key, raw response, headers, cookies, account identifier, payment data, billing history, or monetary value.
