# How DeepSeek-Reasonix Tracks Usage and Billing for API Costs: A Technical Deep Dive

> DeepSeek-Reasonix tracks API costs by parsing token usage and querying wallet endpoints. Discover how this technical deep dive displays real-time balance via server-sent events for your UI.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: technical-deep-dive
- Published: 2026-06-24

---

**DeepSeek-Reasonix tracks API costs by parsing token usage from provider responses via a generic `Usage` struct and optionally queries a DeepSeek-style wallet endpoint to display real-time balance, all surfaced through server-sent events to the UI.**

DeepSeek-Reasonix (from the `esengine/DeepSeek-Reasonix` repository) implements a lightweight, read-only telemetry system that monitors every LLM request without interfering with the provider's billing logic. The architecture relies on two complementary mechanisms: **provider usage telemetry** that extracts token counts from streaming responses, and an optional **wallet-balance query** that fetches real-time account balance from DeepSeek-compatible endpoints.

## Provider-Side Usage Telemetry

### The Usage Struct and Token Parsing

At the core of the tracking system is the generic `provider.Usage` type, defined within each provider implementation (see the `wireUsage` structs in [`internal/provider/openai/openai.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/provider/openai/openai.go) and similar files). This struct normalizes diverse provider formats into a single schema:

```go
type Usage struct {
    PromptTokens       int     // tokens sent to the model
    CompletionTokens   int     // tokens generated by the model
    TotalTokens        int     // sum of the above (may include cached tokens)
    CacheHitTokens     int     // tokens read from cache
    CacheMissTokens    int     // tokens that missed the cache
    Cost               float64 // optional: USD cost supplied by the provider
    CostUsd            float64 // alias used by some providers
    Currency           string  // optional currency code (e.g., "USD")
    FinishReason       string  // why the generation stopped
}

```

When a provider streams a response, the implementation parses the `usage` JSON field and populates this struct. If the provider supplies `cost` or `costUsd` fields, Reasonix forwards these values directly without recalculating them locally.

### Streaming Response Handling

Each provider implementation in `internal/provider/*` contains a streaming response handler that extracts the `usage` object from the JSON payload. For example, in [`internal/provider/openai/openai.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/provider/openai/openai.go), the handler monitors the SSE stream for the final message containing usage statistics.

Once parsed, the controller emits an `event.Usage` event via the `Emit` method in `internal/control.Controller`. This event encapsulates the token counts and cost data for transmission to the frontend.

### SSE Broadcasting to the Frontend

Usage data reaches the UI through Server-Sent Events (SSE). In [`internal/serve/serve.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/serve/serve.go), the controller writes the usage struct to the broadcast channel:

```go
// Event emission to connected clients
bc.Emit(event.Usage{
    PromptTokens:     usage.PromptTokens,
    CompletionTokens: usage.CompletionTokens,
    Cost:             usage.Cost,
    Currency:         usage.Currency,
})

```

This ensures that token counts and costs update in real-time as the model generates completions.

## Frontend Aggregation and Cost Display

The frontend receives raw usage events through [`desktop/frontend/src/lib/useController.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/useController.ts), which accumulates metrics per turn, per session, and for the entire application lifecycle. The UI maintains aggregates such as `usageTotalTokens` and updates the session ribbon with live cost calculations.

Currency formatting occurs via `fmtMoney`, which derives the appropriate symbol (¥, $, etc.) from the `provider.Usage.Currency` field. If a provider omits usage data entirely, Reasonix continues to function, but cost-related UI elements remain blank rather than displaying erroneous estimates.

## Wallet Balance and Billing Queries

### The Balance Fetch Implementation

For users requiring a hard balance read-out, Reasonix implements a dedicated billing client in [`internal/billing/balance.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/billing/balance.go). This module queries the DeepSeek-style endpoint `GET /user/balance` using the user's API key:

```go
// Fetch queries the balance endpoint with a Bearer API key.
func Fetch(ctx context.Context, url, apiKey string) (*Balance, error) {
    return FetchWithClient(ctx, httpClient, url, apiKey)
}

```

The function returns a `*billing.Balance` struct containing availability flags and balance information across currencies (CNY, USD, etc.). If no URL is configured, the function returns `nil, nil` without error, making the feature entirely optional.

### Displaying Wallet Status

The desktop client renders wallet information in the status line. During onboarding and startup, [`desktop/app.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/app.go) (around line 6460) calls `billing.FetchWithClient` to retrieve the current balance. The `Balance.Display()` method selects the primary currency (preferring CNY) and formats it with the appropriate symbol:

- **Primary currency selection**: Prioritizes CNY over USD when available
- **Formatting**: Uses locale-aware symbols (¥, $, etc.)
- **Fallback**: Silently omits the balance display if the endpoint is unreachable or returns an error

## End-to-End Data Flow

The complete lifecycle of a tracked API request follows this sequence:

1. **User invocation** triggers the controller to create a request to the configured provider.
2. **Provider streaming** generates tokens, and the provider parser extracts the `Usage` record from the final response chunk.
3. **Controller emission** pushes an `event.Usage` struct through the SSE broadcaster in [`internal/serve/serve.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/serve/serve.go).
4. **Frontend aggregation** accumulates token counts and cost values via [`useController.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/useController.ts), updating the UI ribbon with `fmtMoney` formatting.
5. **Startup synchronization** calls `billing.Fetch` to retrieve wallet balance, displayed via `Balance.Display()` in the status line.
6. **Error handling** ensures that missing usage data or unreachable balance endpoints degrade gracefully—never blocking the core chat functionality.

## Summary

- **Provider-agnostic telemetry**: The `Usage` struct normalizes token counts across OpenAI, Anthropic, DeepSeek, and other providers via `internal/provider/*` implementations.
- **Real-time streaming**: Cost data flows through SSE via [`internal/serve/serve.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/serve/serve.go), enabling live UI updates without polling.
- **Optional wallet integration**: The [`internal/billing/balance.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/billing/balance.go) client queries DeepSeek-style endpoints for account balance, with graceful degradation when unavailable.
- **Read-only architecture**: Reasonix never writes back to provider APIs; it purely consumes usage metadata and pre-calculated cost fields.
- **Graceful degradation**: Missing usage data or balance errors result in blank UI elements rather than application failures.

## Frequently Asked Questions

### How does DeepSeek-Reasonix handle providers that don't return usage data?

If a provider omits the `usage` field from responses, Reasonix continues operating normally but leaves cost-related UI elements blank. The system does not attempt to estimate costs locally, ensuring users see only provider-verified billing information.

### Where is the API cost calculation performed?

Cost calculation occurs on the provider side. Reasonix extracts the `cost` or `costUsd` fields from the provider's JSON response and forwards them unchanged to the frontend. The application acts as a transparent conduit rather than a billing calculator.

### How does the wallet balance feature work with non-DeepSeek providers?

The wallet balance query targets a DeepSeek-specific endpoint (`GET /user/balance`). For non-DeepSeek providers, this feature remains dormant unless the provider exposes a compatible balance API. Users can configure the balance URL manually, or the feature simply disables itself when the endpoint returns errors or is unspecified.

### What happens if the balance endpoint is unreachable?

When `billing.Fetch` encounters network errors or misconfiguration, it returns `nil` without throwing exceptions. The desktop client ([`desktop/app.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/app.go)) handles this by silently omitting the balance display from the status line, ensuring the chat interface remains fully functional even during billing service outages.