Reference

Usage & billing

Reconcile token usage, request cost, balances, and asynchronous settlement.

On this page

This page is for developers and finance operators reconciling API responses with key balances and request logs.

Usage and cost authority#

Response bodies are passed through. Token fields depend on the protocol and upstream API. When an OpenAI-compatible response includes a finite non-negative usage.cost, that upstream-reported value is the charge authority. Otherwise the billing worker uses its local price table. Reasoning and thinking tokens are charged as output tokens.

For OpenAI-compatible prompt caching, usage.cost already reflects any upstream cache discount. Clients do not need to calculate a separate discount from cached-token fields.

JSONSyntax highlighted
{"usage":{"prompt_tokens":120,"completion_tokens":30,"total_tokens":150,"cost":0.00042}}

If no price can be found, the request can be logged as unpriced for later reconciliation. Binary responses without usage, such as speech audio, can use a request-text estimate that is marked as estimated in the cost breakdown.

Balance and allocation#

Read a key's balance projection with authenticated GET /v1/balance:

BashSyntax highlighted
curl https://api.clssai.com/v1/balance \
  -H "Authorization: Bearer $CLSSAI_API_KEY"
JSONSyntax highlighted
{
  "object": "balance",
  "key": "sk-...abc123",
  "identity": "account",
  "remaining_usd": 2.25,
  "limit_usd": 2.5,
  "recharge_usd": 2,
  "credit_usd": 1,
  "allocated_usd": 0.5,
  "consumption_usd": 0.25,
  "grace_usd": 0.1,
  "expires_at": null,
  "expired": false,
  "disabled": false,
  "tier": "free",
  "tier_until": null,
  "settlement": "asynchronous",
  "note": "consumption_usd settles asynchronously and can lag recent requests by minutes; shared child Keys report the parent balance."
}

identity is one of account, allocated_child, or shared_child. An allocated child has its own funded balance. A shared child returns its parent's balance but never exposes the parent key, and its usage is billed to that parent.

The key limit is recharge_usd + credit_usd - allocated_usd, and remaining_usd = max(limit_usd - consumption_usd, 0). Allocation is the amount assigned to independently funded child keys. expires_at is null for a key with no expiry, otherwise a Unix timestamp in seconds. Expired or disabled keys still receive a 200 response from this balance endpoint, with expired or disabled set to true; callers must inspect those fields. tier is the account's membership (free, plus, pro, or business) and tier_until the end of its current period in Unix seconds, or null on free.

Each key has a small grace_usd amount that can allow a request at the admission boundary. grace_usd is a small request-admission allowance, not spendable balance; do not include it in remaining_usd.

Manage balances at Credits (sign-in required).

Settlement is asynchronous#

Requests enter a billing queue without waiting for settlement. consumption_usd, remaining_usd, and aggregate consumption can therefore lag request completion by several minutes. The response reports settlement: "asynchronous"; do not expect an inference response and the balance projection to change atomically.

Account endpoints#

Four authenticated GET routes report the calling key's own money and usage. They answer from local account data and request logs, never from another account, and never from a third-party console. All four send Cache-Control: no-store and Access-Control-Expose-Headers: Retry-After.

EndpointAnswers
GET /v1/balanceBalance projection and key state (see above).
GET /v1/keyThe calling key's record: label, limit, usage windows, tier, expiry.
GET /v1/creditsLifetime credits purchased and used for the calling key.
GET /v1/generation?id=<id>Cost, tokens, and latency for one of the calling key's own generations.

Key record#

BashSyntax highlighted
curl https://api.clssai.com/v1/key \
  -H "Authorization: Bearer $CLSSAI_API_KEY"
JSONSyntax highlighted
{
  "data": {
    "label": "example-production-key",
    "limit": 5,
    "limit_remaining": 4.945202,
    "limit_reset": null,
    "usage": 0.054798,
    "usage_daily": 0.05479844,
    "usage_weekly": 0.05479844,
    "usage_monthly": 0.05479844,
    "is_free_tier": true,
    "is_management_key": false,
    "is_provisioning_key": false,
    "expires_at": "2026-10-05T02:31:08.000Z",
    "allowed_data_regions": ["global"],
    "free_model_daily_requests": {
      "used": 84,
      "limit": 0,
      "remaining": 0
    },
    "rate_limit": {
      "requests": 30,
      "interval": "10s",
      "note": "Per-key request rate; requests over it are queued or rejected with 429."
    }
  }
}
FieldMeaning
labelDisplay name chosen when the key was created.
limitSpending limit in USD for this key, or a sentinel when unlimited.
limit_remainingRemaining USD under limit.
limit_resetReset cadence for limit, or null.
usageLifetime settled usage in USD for this key.
usage_dailyUsage since 00:00 UTC today.
usage_weeklyUsage since Monday 00:00 UTC.
usage_monthlyUsage since the 1st of the month, 00:00 UTC.
is_free_tierWhether the key is on the free tier.
is_management_keyWhether the key is a management key.
is_provisioning_keyWhether the key is a provisioning key.
expires_atExpiry as an ISO-8601 timestamp, or null when the key does not expire.
allowed_data_regionsData regions this key may use.
free_model_daily_requestsFree-model pool counters: used, limit, remaining.
rate_limitRequest budget for these account queries (see rate limits below).

Daily, weekly, and monthly windows are UTC. Window counters settle asynchronously and can lag recent requests by a few minutes.

Credits summary#

BashSyntax highlighted
curl https://api.clssai.com/v1/credits \
  -H "Authorization: Bearer $CLSSAI_API_KEY"
JSONSyntax highlighted
{"data":{"total_credits":5,"total_usage":0.054798}}
FieldMeaning
total_creditsCurrent wallet total (top-ups + grants − allocations), in USD.
total_usageLifetime spend, in USD.

Generation lookup#

GET /v1/generation?id=<id> returns one generation that belongs to the calling key. Accepted id shapes include gen-…, resp_…, and msg_…. IDs starting with gen- are located from their embedded timestamp; every other shape is searched only in the last 6 hours. Logs become queryable about one minute after the request finishes. Another account's id returns 404 not_found, so the endpoint cannot be used to enumerate other users' traffic.

BashSyntax highlighted
curl "https://api.clssai.com/v1/generation?id=gen-1790569230-BQqOLNDTIJLngMEDcMIR" \
  -H "Authorization: Bearer $CLSSAI_API_KEY"
JSONSyntax highlighted
{
  "data": {
    "id": "gen-1790569230-BQqOLNDTIJLngMEDcMIR",
    "upstream_id": null,
    "total_cost": 8.85e-06,
    "usage": 8.85e-06,
    "cache_discount": null,
    "created_at": "2026-09-28T04:20:31.851Z",
    "model": "openai/gpt-5.4-nano",
    "streamed": false,
    "cancelled": false,
    "latency": 1147,
    "moderation_latency": null,
    "generation_time": 1370,
    "finish_reason": "stop",
    "native_finish_reason": "stop",
    "service_tier": null,
    "tokens_prompt": 13,
    "native_tokens_prompt": 13,
    "tokens_completion": 5,
    "native_tokens_completion": 5,
    "native_tokens_cached": 0,
    "native_tokens_reasoning": 0,
    "api_type": "completions",
    "data_region": "global"
  }
}
FieldMeaning
idGeneration id as queried.
upstream_idProvider-side id when one was recorded, otherwise null.
total_costSettled charge for this generation in USD.
usageSame figure as total_cost.
cache_discountPrompt-cache discount applied to the charge, or null.
created_atCompletion time in UTC.
modelResolved author/model ID.
streamedWhether the response was streamed.
cancelledWhether the request was cancelled.
latencyEnd-to-end latency in milliseconds.
moderation_latencyModeration time in milliseconds, or null.
generation_timeGeneration time in milliseconds.
finish_reasonNormalized finish reason, for example stop or length.
native_finish_reasonFinish reason as reported by the model.
service_tierService tier used, or null.
tokens_promptPrompt tokens billed.
native_tokens_promptPrompt tokens as reported by the model.
tokens_completionCompletion tokens billed.
native_tokens_completionCompletion tokens as reported by the model.
native_tokens_cachedCached prompt tokens reported by the model.
native_tokens_reasoningReasoning tokens reported by the model.
api_typeRequest surface that produced the generation, for example completions.
data_regionData region that served the request.

Missing id, a foreign id, or a still-unwritten log returns 404 with code not_found. A missing id query parameter returns 400 with code missing_id.

How the numbers line up#

/v1/balance, /v1/key, and /v1/credits share one ledger for the calling key:

/v1/balance/v1/key/v1/credits
limit_usdlimittotal_credits
consumption_usdusagetotal_usage
remaining_usdlimit_remainingtotal_credits - total_usage
expires_at (Unix seconds)expires_at (ISO-8601)—

Use /v1/balance for the admission projection (remaining_usd, grace_usd, expired, disabled). Use /v1/key for label, tier, and window counters. Use /v1/credits when a client only needs two lifetime totals. Use /v1/generation to reconcile a single request's charge. All four lag recent inference by the same asynchronous settlement delay.

Rate limits and errors#

These account queries have their own budgets, separate from inference traffic:

EndpointBudget
GET /v1/key, GET /v1/credits30 requests per 10 seconds, shared per key.
GET /v1/generation5 requests per 10 seconds per key, and 1 in-flight lookup per key.

Exceeding a budget returns 429 with an integer Retry-After header in seconds and this body:

JSONSyntax highlighted
{"error":{"message":"Too many account requests. Retry after 1 seconds.","type":"invalid_request_error","param":null,"code":"rate_limited"}}

Retry-After is the number of seconds until the next slot. Concurrent generation lookups above one return the same 429 with Retry-After: 1. Account-query 429 responses are distinct from the free daily pool 429; see Errors & rate limits.

Reconcile request logs#

The key appears in the management path, so construct this URL only in trusted server tooling and never log it. The range, page, and page_size query parameters select the time window, result page, and requested rows per page.

BashSyntax highlighted
curl "https://api.clssai.com/key/$CLSSAI_API_KEY/logs.json?range=24h&page=1&page_size=30" \
  -H "Content-Type: application/json"

The top-level JSON object contains:

FieldMeaning
errorError value reported by the endpoint.
rangeEffective time-window selection.
sourceLog source reported for the result set.
pageCurrent result page.
page_sizeEffective number of rows per page.
totalTotal number of matching rows.
total_pagesTotal number of result pages.
window_startStart of the selected time window.
window_endEnd of the selected time window.
itemsArray of request-log rows.

Each items[] row contains:

FieldMeaning
timeRequest time.
providerProvider recorded for the request.
statusRecorded status label.
status_codeRecorded HTTP status code.
cachedWhether this response was returned from an upstream gateway cache.
modelModel recorded for the request.
tokens_inRecorded input-token count.
tokens_outRecorded output-token count.
costRecorded request cost.
countCount value reported for the row.
duration_msRecorded request duration in milliseconds.
upstream_idUpstream identifier recorded for the request.
sourceSource recorded for the request.

For native Anthropic requests, tokens_in and tokens_out omit the cache_creation_input_tokens and cache_read_input_tokens counters, so those two logged token values alone cannot be used to reproduce cost.

Free models and the daily pool#

A complete model ID ending in :free has zero local token prices, unless an upstream-reported cost overrides them. Free users also share a separate global daily pool. When that pool is exhausted, the gateway returns 429. These are distinct limits.

Common mistakes#

  • Do not assume settlement is real-time.
  • Do not subtract only consumption; account for recharge, credit, and allocated amounts.
  • Do not assume a 200 balance response means the key is active; inspect expired and disabled.
  • Do not add grace_usd to available balance.
  • Do not publish or log a key-bearing management URL.
  • Preserve the complete author/model:free or author/model:batch ID.
  • Include /v1 in OpenAI SDK base URLs, omit it from the Anthropic SDK base URL, and call from a server.
  • Check empty streaming choices arrays and retain cf-ray for inference tracing.
  • Do not expect /v1/key window counters to update instantly; they share the asynchronous settlement delay.
  • Do not treat /v1/generation as a public log search: only the calling key's own ids resolve, and anything outside the recent window returns 404 not_found.
  • Honor Retry-After on account-endpoint 429 rate_limited responses instead of retrying immediately.
Need a hand?

Find answers to common questions or diagnose a failed request.

Frequently asked questions →Troubleshoot errors →