Skip to content

Log Query & Export

For /getDailyList and /getDailySummary, use the dedicated Formal Billing Statement API (v2.2). This page primarily covers live usage and log APIs.

Use log and usage endpoints to audit request history, build internal reporting, and review usage.

Fetch logs

http
GET /api/log/self?start_timestamp=1711929600&end_timestamp=1713830400

Export usage

http
GET /api/log/self/export?start_timestamp=1711929600&end_timestamp=1713830400

Log query and export are dashboard management APIs and require a signed-in user session. Admins can use /api/log/ and /api/log/export for all logs.

Daily usage

Use the daily usage endpoint for internal reporting, financial reconciliation, or customer-facing billing pages. The endpoint aggregates successful consumption and refunds by day, and returns request counts, token usage, raw quota, and the server-side converted billing amount.

Endpoint

http
GET /api/usage/daily
Authorization: Bearer YOUR_BILLING_READ_TOKEN

Authentication

For external billing integrations, use a billing read-only token with the bill-... prefix. Users can generate or reset it from Console > Personal Settings > Security Settings. Each user has one billing read-only token; resetting it immediately invalidates the previous token.

Billing read-only tokens can only query billing data. They cannot call model endpoints such as /v1/models or /v1/chat/completions.

The same bill-... token generated by an enterprise main account can also call the enterprise aggregate usage endpoint. This permission only reads billing data for sub-accounts belonging to that enterprise. It does not grant model access, sub-account management, or API key management.

You can also use a regular API key to query daily usage for that API key only:

http
GET /api/usage/daily?start_timestamp=1711929600&end_timestamp=1713830400&timezone_offset=0
Authorization: Bearer YOUR_API_KEY

Query user-level daily usage with a billing read-only token:

http
GET /api/usage/daily?scope=user&start_timestamp=1711929600&end_timestamp=1713830400&timezone_offset=0
Authorization: Bearer YOUR_BILLING_READ_TOKEN

Query daily usage for one API key owned by the user:

http
GET /api/usage/daily?scope=token&token_id=28&start_timestamp=1711929600&end_timestamp=1713830400&timezone_offset=0
Authorization: Bearer YOUR_BILLING_READ_TOKEN

Query Parameters

ParameterTypeRequiredDescription
start_timestampintegerNoStart time as a Unix timestamp in seconds. Defaults to the last 30 days.
end_timestampintegerNoEnd time as a Unix timestamp in seconds. Defaults to now.
timezone_offsetintegerNoTimezone offset in seconds for day buckets. Defaults to 0 (UTC); allowed range: -50400 to 50400.
scopestringNouser or token. Billing read-only tokens default to user; API keys can only use token.
token_idintegerNoQuery one API key. Required when using a billing read-only token with scope=token, and the token must belong to the current user.
model_namestringNoFilter by model, for example gpt-4o-mini.
group_by_modelbooleanNoSet to true to split rows by both date and model. Also accepts 1 and yes.

The maximum time range is 366 days.

Timezone Rules

The daily usage and enterprise billing endpoints use the same timezone rules. If timezone_offset is omitted, both default to UTC (0). Callers may still provide another valid offset for compatibility. start_timestamp and end_timestamp remain Unix timestamps in seconds; the timezone parameter only affects daily and monthly period boundaries.

Response Example

json
{
  "success": true,
  "message": "",
  "data": {
    "object": "daily_usage",
    "scope": "user",
    "user_id": 1,
    "token_id": 0,
    "start_timestamp": 1711929600,
    "end_timestamp": 1713830400,
    "timezone": "UTC",
    "timezone_offset": 0,
    "billing_currency": "USD",
    "billing_unit_type": "currency",
    "billing_amount_is_invoice_amount": false,
    "billing_amount_basis": "current_site_display_config",
    "quota_per_unit": 500000,
    "data_status": "preliminary",
    "is_final": false,
    "generated_at": 1713830401,
    "data": [
      {
        "date": "2024-04-01",
        "start_timestamp": 1711900800,
        "end_timestamp": 1711987199,
        "request_count": 10,
        "prompt_tokens": 269,
        "completion_tokens": 11645,
        "token_used": 11914,
        "cache_read_tokens": 200,
        "cache_creation_tokens": 100,
        "cache_creation_5m_tokens": 80,
        "cache_creation_1h_tokens": 20,
        "quota": 657472,
        "billing_amount": 1.314944,
        "billing_currency": "USD",
        "usage_amount": 1.314944,
        "usage_unit": "USD"
      }
    ]
  }
}

When group_by_model=true, each row also includes model_name:

json
{
  "date": "2024-04-01",
  "model_name": "gpt-4o-mini",
  "request_count": 10,
  "prompt_tokens": 269,
  "completion_tokens": 11645,
  "token_used": 11914,
  "cache_read_tokens": 200,
  "cache_creation_tokens": 100,
  "cache_creation_5m_tokens": 80,
  "cache_creation_1h_tokens": 20,
  "quota": 657472,
  "billing_amount": 1.314944,
  "billing_currency": "USD",
  "usage_amount": 1.314944,
  "usage_unit": "USD"
}

Fields

FieldDescription
successWhether the request succeeded.
data.objectAlways daily_usage.
data.scopeActual query scope: user for the whole user, or token for one API key.
data.user_idCurrent user ID.
data.token_idAPI key ID when querying one key; 0 for user-level queries.
data.timezoneEffective day-bucket timezone. It is UTC when timezone_offset is omitted.
data.billing_currencyCurrent display currency or unit, for example USD, CNY, or TOKENS.
data.billing_unit_typecurrency for currency display, or quota for raw quota display.
data.billing_amount_is_invoice_amountAlways false. This endpoint returns a usage display value, not an invoice payable amount.
data.billing_amount_basisCurrently current_site_display_config, meaning conversion uses the site configuration at query time.
data.quota_per_unitConversion base between raw quota and a standard currency unit. For example, with 500000, 657472 quota = 1.314944 USD.
data.data_statusCurrently preliminary, indicating that the endpoint returns a live aggregate.
data.is_finalCurrently false; the endpoint does not yet promise an issued formal statement.
data.generated_atResponse generation time as a Unix timestamp in seconds.
data.dataDaily usage rows.
dateBilling date, bucketed by timezone_offset.
request_countSuccessful consumed request count. Refund rows do not increase this value.
prompt_tokensTotal input tokens.
completion_tokensTotal output tokens.
token_usedprompt_tokens + completion_tokens.
cache_read_tokensTotal cache-read tokens.
cache_creation_tokensTotal cache-creation tokens.
cache_creation_5m_tokensCache-creation tokens for the 5-minute TTL.
cache_creation_1h_tokensCache-creation tokens for the 1-hour TTL.
quotaRaw net platform usage. Consumption is positive; refunds are negative.
billing_amountConverted billing amount or display unit according to the current server configuration.
billing_currencyCurrency or display unit for the row.
usage_amountExplicit semantic alias of billing_amount, representing a usage display value.
usage_unitExplicit semantic alias of billing_currency.

Amount Conversion

quota is the raw internal value used for precise billing and reconciliation. For customer-facing display, use the returned billing_amount and billing_currency directly instead of reimplementing exchange rates on the client.

When the site uses the default USD display:

text
billing_amount = quota / quota_per_unit

For example, with quota_per_unit = 500000, 21301158 quota = 42.602316 USD.

If the site is configured to display CNY, a custom currency, or tokens, the endpoint returns the converted billing_amount and billing_currency based on the current server configuration.

billing_amount is a usage display value, not the final invoice amount before tax. Taxes, contractual adjustments, minimum commitments, and other invoice line items are outside this endpoint.

With the current site configuration, both billing_currency and usage_unit are USD and do not return TOKENS. TOKENS can appear only if the server-side billing display mode is explicitly changed to token/quota mode; that configuration is not currently enabled. For actual model token counts, use prompt_tokens, completion_tokens, and token_used.

When billing_currency is TOKENS, billing_amount equals quota. Here, TOKENS means the platform's raw quota unit. It is not an ISO currency and is not guaranteed to equal token_used; use prompt_tokens, completion_tokens, and token_used for actual model token counts.

Historical usage is not repriced after later model pricing changes.

Formal Billing Statement API (v2.2)

Use these endpoints for API key × billing day × model × token-type detail reconciliation or account-level daily summaries. They coexist with the real-time usage APIs:

Download the OpenAPI 3.0 specification for Apifox, Postman, Swagger UI, YApi, Insomnia, or client generation.

http
GET /getDailyList?startDate=2026-07-01&endDate=2026-07-23&pageSize=100&pageNum=1
GET /getDailySummary?startDate=2026-07-01&endDate=2026-07-23&pageSize=31&pageNum=1
Authorization: Bearer YOUR_BILLING_READ_TOKEN

Both endpoints use the enterprise main account's read-only bill-... token. Model API keys and tokens owned by personal or enterprise sub-accounts are rejected. Responses use the {code,message,data} envelope, with code: 0, data.total, and data.rows on success. data.provider is an optional model/inference-provider field. The current version omits it because a mixed-model statement cannot always identify one reliable, unambiguous provider; it never returns an empty string or substitutes cubicspace for the model provider.

data.total is always the total number of matching records, independent of the current page. A query with no data returns total: 0 and rows: []. A page beyond the last page keeps the real total and returns an empty rows array.

Required query parameters are startDate, endDate, pageSize, and pageNum. Optional userId and userName filters can select a direct account; passing the authenticated enterprise main identity keeps all linked accounts. Detail queries support up to 92 days and 100 rows per page. Summary queries support up to 366 days and 400 rows per page.

For /getDailyList, the response account is the API key name captured when the statement is issued. Multiple keys under one direct account appear in separate detail rows. Legacy details without a key name fall back to the account username and then the stored account identifier. userId and userName still filter enterprise accounts. /getDailySummary is not split by API key; its account remains the account username or stored identifier.

Each /getDailyList row has this unique grain:

text
billDay × API key × modelName × tokenType × currency × entryType

One model can therefore return separate rows for text input, text output, 5-minute cache creation, 1-hour cache creation, and cache reads. Supported token types are textInputTokens, textOutputTokens, imageInputTokens, imageOutputTokens, videoInputTokens, videoOutputTokens, audioInputTokens, audioOutputTokens, cacheCreationTokens5m, cacheCreationTokens1h, cacheTokens, and reasoningTokens. Actual model usage is normalized into independent text, image, video, audio, and cache fields when each consumption log is written. Asynchronous tasks use their model modality, so image, video, or audio usage is not recorded as generic text tokens. A model produces detail rows only for token categories with actual nonzero usage. Missing upstream token details are not fabricated, except for one legacy cache-creation compatibility rule: when a log contains only an aggregate cache-creation count, or that total exceeds the recorded 5-minute plus 1-hour counts, the positive unclassified remainder is assigned to cacheCreationTokens5m. cacheCreationTokens1h uses only an explicitly recorded 1-hour count. If the explicit split exceeds the aggregate total, the explicit split is preserved without a negative adjustment. A fixed-price service with no upstream token count may return "0" while preserving its settled amount. The optional price field is not returned by the current version; use the three amount fields as authoritative, and do not derive a unit price when tokenCount is zero or money was allocated across weighted token types.

Normal rows omit entryType and mean normal. Refund rows use refund with negative token counts and amounts; the original row is not overwritten. adjustment is reserved by the contract but is not emitted by the current version.

Amounts are fixed 8-decimal strings. subtotalBeforeTax is before contract discount and tax, subtotalAfterDiscount is after the contract discount and before tax, and totalAmountAfterTax is the final after-tax amount. discountDetail.rate is the contract rate captured in the issued statement: an 86% retained-rate policy always returns 0.86000000 instead of a nearby value caused by per-token-type money allocation and 8-decimal rounding. Contract discounts are scoped by enterprise main account and service type, automatically apply to all direct sub-accounts and all models/token types in that service, and can be overridden for one linked account. For example, Claude uses one service discount rather than separate input, output, or cache discounts. Policies are append-only by effective date. When an enterprise or service has no contract policy, both subtotal fields use the actual settled amount; a general group multiplier is not reported as a contract discount.

/getDailySummary returns account-level net amounts by billDay × account × currency. Each amount exactly equals all token-level detail rows that belong to that account for the same date and currency, including refunds. Because detail account values display API key names, clients cannot join the two endpoints by comparing the exposed account strings alone.

Daily summary response

For /getDailySummary, data.total counts matching billDay × account × currency summary rows. Each row contains billMonth, billDay, billingDateTimezone, account, currency, the three amount fields, and entryCount, which is the number of matching /getDailyList rows.

Request:

http
GET /getDailySummary?startDate=2026-07-23&endDate=2026-07-23&userName=enterprise-subaccount&pageSize=10&pageNum=1
Authorization: Bearer bill-YOUR_BILLING_READ_TOKEN

Response:

json
{
  "code": 0,
  "message": "success",
  "data": {
    "total": 1,
    "rows": [
      {
        "billMonth": "202607",
        "billDay": "2026-07-23",
        "billingDateTimezone": "utc+0",
        "account": "enterprise-subaccount",
        "currency": "USD",
        "subtotalBeforeTax": "1.20475000",
        "subtotalAfterDiscount": "1.01975726",
        "totalAmountAfterTax": "1.01975726",
        "entryCount": 34
      }
    ]
  }
}

Pagination, ordering, and zero-usage days

  • /getDailyList uses stable billDay DESC, modelName ASC, tokenType ASC, currency ASC ordering, with the internal issued-row order as the final tie-breaker.
  • /getDailySummary uses billDay DESC, the internal stable account order, and currency ASC; clients must not assume lexical ordering by the exposed account name.
  • Detail pagination operates on token-type detail rows, not days. Start with pageNum=1 and continue until the accumulated row count equals data.total.
  • Oversized pageSize values are clamped to 100 for details and 400 for summaries.
  • Zero-usage days do not produce detail or summary rows.

Formal statements use UTC+0 billing dates. The system issues the previous UTC calendar day's statement at 02:00 UTC (10:00 Asia/Shanghai); before 02:00 UTC, the latest eligible day is D-2. Automatic issuance covers every enabled enterprise main account. Formal billing policies configure discounts and tax rates; they do not enable or disable statement generation. When no policy applies, the statement is still generated using the actual settled amount and a 1.0 retained rate. A database uniqueness marker makes issuance single-writer across instances. One enterprise failure does not block the others and is retried every five minutes. Formal statement endpoints return only issued data; data for dates that have not been issued is neither generated nor exposed. When a query range includes both issued and unissued dates, the response contains only the issued dates. The settled amount and quota conversion scale are captured with each usage log. Issued rows are not repriced after model pricing, global conversion-scale, discount, or tax changes; later refunds are appended as negative entries on their settlement date.

Background statement issuance is controlled by BILLING_STATEMENT_FREEZE_ENABLED; the environment-variable name is retained as an internal compatibility identifier. It defaults to true; changing it requires a service restart. Setting it to false stops startup and scheduled 02:00 UTC issuance. Read endpoints are always read-only: they query issued data and never generate or issue a date. During a first deployment or contract-policy setup, set BILLING_STATEMENT_FREEZE_ENABLED=false to stop statement generation. Set BILLING_STATEMENT_SERVICE_AVAILABLE=false as well only when the formal statement query service must also be unavailable. After schema migration, enterprise policies, and Billing Tokens are configured, enable the required switches according to the release plan and restart the service.

The current formal response does not expose isFinal or latestAvailableBillDay. Querying a current day or D-1 that has not been issued may return code: 0, total: 0, and rows: []; that empty response does not prove that the date was issued with zero usage. Clients must restrict endDate according to the 02:00 UTC issuance rule and retry when necessary.

Formal statement errors

Formal statement errors use a different envelope from the real-time usage endpoints:

json
{
  "code": 40001,
  "message": "startDate is invalid, expected format: yyyy-MM-dd",
  "data": {}
}
HTTPcodeMeaning
40040001Invalid date, pagination, or userId format
40040002Missing startDate, endDate, pageSize, or pageNum
40040003Reversed dates, detail range over 92 days, or summary range over 366 days
40140100Missing, invalid, expired, or reset token; disabled owner account; or a model API key was used
40340300Valid token owned by an enabled account that is not an enterprise main account
42942900The enterprise main account exceeded the formal statement request limit
50050000Server or database failure while freezing or querying
50350300System maintenance or formal billing service temporarily unavailable

After successful billing-token authentication, formal statement requests are rate-limited independently by enterprise main account rather than source IP. The default limit is 120 requests per 60 seconds for each enterprise main account. A rejected response includes Retry-After with the minimum number of seconds to wait. Deployments may override the threshold; batch clients should still use the largest allowed page size and retry according to Retry-After.

Enterprise Aggregate Usage

An enterprise main account can use its billing read-only token to retrieve billing data for all direct enterprise sub-accounts:

http
GET /api/usage/enterprise?start_timestamp=1711929600&end_timestamp=1713830400&granularity=daily&timezone_offset=0
Authorization: Bearer YOUR_BILLING_READ_TOKEN

granularity accepts daily or monthly and defaults to daily. Enterprise and daily usage endpoints use the same timezone rules: timezone_offset defaults to UTC (0) when omitted, and callers can provide another offset to change daily and monthly boundaries. The response contains each sub-account's quota, request counts, input/output tokens, model-category totals, usage display fields, and the same completeness metadata used by the daily usage endpoint.

ParameterTypeRequiredDescription
start_timestampintegerNoStart time as a Unix timestamp in seconds. Defaults to one month before the current time.
end_timestampintegerNoEnd time as a Unix timestamp in seconds. Defaults to the current time.
granularitystringNodaily or monthly; defaults to daily.
timezone_offsetintegerNoTimezone offset in seconds for daily and monthly buckets. Defaults to 0 (UTC); allowed range: -50400 to 50400.

Example response:

json
{
  "success": true,
  "message": "",
  "data": {
    "object": "enterprise_usage",
    "total_quota": 750000,
    "prompt_tokens": 1000,
    "completion_tokens": 500,
    "token_used": 1500,
    "cache_read_tokens": 200,
    "cache_creation_tokens": 100,
    "cache_creation_5m_tokens": 80,
    "cache_creation_1h_tokens": 20,
    "billing_amount": 1.5,
    "billing_currency": "USD",
    "usage_amount": 1.5,
    "usage_unit": "USD",
    "billing_amount_is_invoice_amount": false,
    "billing_amount_basis": "current_site_display_config",
    "timezone": "UTC",
    "timezone_offset": 0,
    "data_status": "preliminary",
    "is_final": false,
    "items": [
      {
        "sub_user_id": 2,
        "username": "team-a",
        "display_name": "Team A",
        "total_quota": 750000,
        "prompt_tokens": 1000,
        "completion_tokens": 500,
        "token_used": 1500,
        "cache_read_tokens": 200,
        "cache_creation_tokens": 100,
        "cache_creation_5m_tokens": 80,
        "cache_creation_1h_tokens": 20,
        "usage_amount": 1.5,
        "usage_unit": "USD",
        "buckets": [
          {
            "period": "2026-07-01",
            "period_start": 1782835200,
            "quota": 750000,
            "request_count": 10,
            "prompt_tokens": 1000,
            "completion_tokens": 500,
            "token_used": 1500,
            "cache_read_tokens": 200,
            "cache_creation_tokens": 100,
            "cache_creation_5m_tokens": 80,
            "cache_creation_1h_tokens": 20,
            "usage_amount": 1.5,
            "usage_unit": "USD",
            "model_family_quotas": {
              "gpt": 500000,
              "claude": 250000
            }
          }
        ]
      }
    ]
  }
}

Only a bill-... token owned by an enterprise main account can call this endpoint. Personal and enterprise sub-account tokens receive 403; regular model API keys receive 401.

The enterprise endpoint returns prompt_tokens, completion_tokens, and token_used at the top level, for each sub-account, and in every daily or monthly bucket. token_used = prompt_tokens + completion_tokens.

The daily usage and enterprise billing endpoints also return cache_read_tokens, cache_creation_tokens, cache_creation_5m_tokens, and cache_creation_1h_tokens. If the model or upstream does not provide the corresponding cache detail, the field is 0. The 5-minute and 1-hour fields are components of cache_creation_tokens and must not be added to the total again.

Data Completeness and D-1

/api/usage/daily and /api/usage/enterprise remain real-time aggregate APIs; data_status=preliminary and is_final=false identify data that has not been formally issued. Use /getDailyList and /getDailySummary when a fixed D-1 statement is required. Formal statements issue the previous UTC calendar day at 02:00 UTC.

Error Response

json
{
  "success": false,
  "message": "token invalid"
}

Common errors:

HTTP StatusScenario
401Missing token, invalid token, expired token, or a billing read-only token that has been reset.
403The user is disabled.
500Server or database error.

Invalid query parameters also return success=false, such as start_timestamp being greater than end_timestamp, a range longer than 366 days, or timezone_offset outside the allowed range.

Integration Notes

  • Use a billing read-only token for external billing systems instead of a regular API key.
  • Store the token as a secret. Do not expose it in frontend source code, logs, or public documentation.
  • For monthly billing, pass explicit start_timestamp, end_timestamp, and timezone_offset values to avoid month-boundary drift.
  • Use quota for exact reconciliation, and use billing_amount with billing_currency for user-facing display.