> ## Documentation Index
> Fetch the complete documentation index at: https://gccai.heqingsong.uk/llms.txt
> Use this file to discover all available pages before exploring further.

# Query Usage and Spending

>  - Query spending and request statistics for a specified time range
- Filter by model and group by model or calendar day
- Query usage for the current API Key or the entire account
- Returns USD amounts, credits, request counts, and token usage 

Use an API Key to query spending within a specified time range, filter by model, and group by model, calendar day, or both. This endpoint returns aggregated results directly; no task creation or task-status polling is required.

```bash cURL theme={null}
curl --get 'https://gccai.heqingsong.uk/v1/usage' \
  --header 'Authorization: Bearer <token>' \
  --data-urlencode 'start=2026-09-01T00:00:00+08:00' \
  --data-urlencode 'end=2026-09-08T00:00:00+08:00' \
  --data-urlencode 'group_by=model'
```

```python Python theme={null}
import requests

response = requests.get(
    "https://gccai.heqingsong.uk/v1/usage",
    headers={"Authorization": "Bearer <token>"},
    params={
        "start": "2026-09-01T00:00:00+08:00",
        "end": "2026-09-08T00:00:00+08:00",
        "group_by": "model",
    },
    timeout=30,
)

payload = response.json()
if not response.ok or not payload.get("success"):
    message = payload.get("error", {}).get("message", "Usage query failed")
    raise RuntimeError(f"HTTP {response.status_code}: {message}")

print(payload["data"]["total"])
print(payload["data"]["items"])
```

```javascript JavaScript theme={null}
const url = new URL("https://gccai.heqingsong.uk/v1/usage");
url.search = new URLSearchParams({
  start: "2026-09-01T00:00:00+08:00",
  end: "2026-09-08T00:00:00+08:00",
  group_by: "model",
}).toString();

const response = await fetch(url, {
  headers: { Authorization: "Bearer <token>" },
});
const payload = await response.json();

if (!response.ok || !payload.success) {
  throw new Error(
    `HTTP ${response.status}: ${payload.error?.message ?? "Usage query failed"}`,
  );
}

console.log(payload.data.total);
console.log(payload.data.items);
```

```json 200 theme={null}
{
  "success": true,
  "data": {
    "scope": "key",
    "start": 1788192000,
    "end": 1788796800,
    "tz": "Asia/Shanghai",
    "group_by": "model",
    "total": {
      "amount_usd": 12.3456,
      "credits": 123.456,
      "requests": 1834,
      "prompt_tokens": 902311,
      "completion_tokens": 215044
    },
    "items": [
      {
        "model": "gpt-5.6-luna",
        "amount_usd": 9.1271,
        "credits": 91.271,
        "requests": 1520,
        "prompt_tokens": 880120,
        "completion_tokens": 201300
      },
      {
        "model": "sora-2",
        "amount_usd": 3.2185,
        "credits": 32.185,
        "requests": 314,
        "prompt_tokens": 22191,
        "completion_tokens": 13744
      }
    ]
  }
}
```

```json 400 theme={null}
{
  "success": false,
  "error": {
    "code": "range_too_large",
    "message": "Time range must not exceed 31 days.",
    "type": "usage_query_error"
  }
}
```

## Authentication

**Authorization** `string` *required*

Authenticate with the same API Key used for model calls, using a Bearer Token. Get a key from the [API Key management page](https://gccai.heqingsong.uk/keys).

```
Authorization: Bearer YOUR_API_KEY
```

> [!NOTE]
>
> Queries are available even with a zero balance. This endpoint does not check the balance, but still checks API Key status, expiration, IP allowlists, and account status.

## Endpoints

```text theme={null}
GET /v1/usage
GET /usage
```

Both endpoints provide the same functionality and support CORS. Keep your API Key private; do not expose it in public frontend code.

## Request parameters

All parameters are passed as URL query parameters.

**start** `integer | string`

Inclusive start time. Accepts a Unix timestamp in seconds or an RFC3339 string with a timezone, such as `2026-09-01T00:00:00+08:00`.

Defaults to 24 hours before `end` when omitted. Timestamps use seconds, not milliseconds.

**end** `integer | string`

Exclusive end time. Uses the same formats as `start` and defaults to the current time when omitted.

Must be later than `start`, and `end - start` must not exceed 31 days.

**model** `string`

Model names; all models are included when omitted. Separate multiple models with commas, up to `50` models.

Exact, case-insensitive matching. Wildcards are not supported.

Example: `gpt-5.6-luna,sora-2`

**group\_by** `string` (default: none)

Grouping options:

* `none`: totals only; `items` is an empty array
* `model`: group by model
* `date`: group by calendar day
* `model,date`: group by both model and calendar day

**tz** `string` (default: Asia/Shanghai)

IANA timezone name; defaults to `Asia/Shanghai`.

Only affects calendar-day boundaries when `group_by` includes `date`; it does not change the query start or end instants. RFC3339 times are still parsed using their own timezone offsets.

**scope** `string` (default: key)

Query scope:

* `key`: only the current API Key (default)
* `account`: all API Keys belonging to the account of the current API Key

> [!NOTE]
>
> The query interval is `[start, end)`: inclusive start, exclusive end. Using the same boundary as one query’s `end` and the next query’s `start` avoids counting that boundary twice.
>
> When building URLs manually, encode the `+` in RFC3339 as `%2B`. The examples use cURL `--data-urlencode`, Python `params`, and JavaScript `URLSearchParams` to handle encoding automatically.

## Request examples

### Total spending for the current API Key over the last 24 hours

Omit query parameters to use the default time range, scope, and grouping:

```bash theme={null}
curl 'https://gccai.heqingsong.uk/v1/usage' \
  --header 'Authorization: Bearer <token>'
```

### Daily spending for a specified model across the account

Query spending from September 11 to September 18, 2026, in Beijing time, excluding September 18:

```bash theme={null}
curl --get 'https://gccai.heqingsong.uk/v1/usage' \
  --header 'Authorization: Bearer <token>' \
  --data-urlencode 'start=1789056000' \
  --data-urlencode 'end=1789660800' \
  --data-urlencode 'model=gpt-5.6-luna' \
  --data-urlencode 'group_by=date' \
  --data-urlencode 'scope=account' \
  --data-urlencode 'tz=Asia/Shanghai'
```

### Group by model and calendar day

```bash theme={null}
curl --get 'https://gccai.heqingsong.uk/v1/usage' \
  --header 'Authorization: Bearer <token>' \
  --data-urlencode 'start=2026-09-01T00:00:00+08:00' \
  --data-urlencode 'end=2026-09-08T00:00:00+08:00' \
  --data-urlencode 'model=gpt-5.6-luna,sora-2' \
  --data-urlencode 'group_by=model,date' \
  --data-urlencode 'tz=Asia/Shanghai'
```

With this grouping, each `items` entry contains both `model` and `date`.

## Response fields

**success** `boolean`

Whether the query succeeded: `true` on success, `false` for usage-query errors.

**data** `object`

On success, contains the query range, totals, and grouped details.

**data properties**

**scope** `string`

Query scope: `key` or `account`.

**start** `integer`

Actual query start time as a Unix timestamp in seconds, inclusive.

**end** `integer`

Actual query end time as a Unix timestamp in seconds, exclusive.

**tz** `string`

Timezone used for calendar-day grouping.

**group\_by** `string`

Grouping: `none`, `model`, `date`, or `model,date`.

**total** `object`

Totals within the query range; see the statistics below.

**items** `object[]`

Grouped details, sorted by `amount_usd` in descending order. Empty when `group_by=none`. Each entry includes the statistics below.

* Entries include `model` when `group_by` includes `model`
* Entries include `date` when `group_by` includes `date`, formatted as `YYYY-MM-DD` with calendar days determined by `tz`

`data.total` and `data.items[]` share these statistics:

| Field | Type | Description |
| - | - | - |
| `amount_usd` | number | USD amount, rounded to 6 decimal places |
| `credits` | number | Platform credits, equal to `amount_usd × 10`, matching the units displayed on the website |
| `requests` | integer | Number of successfully billed calls |
| `prompt_tokens` | integer | Input tokens; usually 0 for image/video models billed per request or per second |
| `completion_tokens` | integer | Output tokens; usually 0 for image/video models billed per request or per second |

**error** `object`

Returned for usage-query errors, with `code`, `message`, and `type`; `type` is `usage_query_error`. Authentication errors with HTTP 401 / 403 are returned by the authentication layer.

## Rate limits and caching

* Up to `60` queries per API Key per minute; global API rate limits also apply
* Results with identical parameters are cached for `60` seconds; the `X-Usage-Cache` response header is `hit` or `miss`
* Usage records are typically available within 1 second, but the last minute of data may be incomplete, with additional cache delay
* Poll no more frequently than once a minute; do not use this endpoint as a real-time billing notification

## Accounting rules

* Uses successfully billed call records, the same data as the website dashboard
* Failed calls and tasks refunded after failure are excluded; no manual offset is needed. Partially successful image batches are billed for the images actually delivered
* Spending is attributed to the billing posting time. Asynchronous image/video tasks are posted at completion, not submission; tasks crossing midnight belong to the completion day
* Deleting and recreating an API Key creates a new Key; querying `scope=key` with the new Key does not include the old Key’s history
* Manual balance adjustments are not call spending and are excluded
* Data after April 27, 2026, is available

## Error handling

| HTTP status | `error.code` | Description |
| - | - | - |
| 400 | `invalid_start` / `invalid_end` | Invalid start or end time format |
| 400 | `invalid_range` | `end` is not later than `start` |
| 400 | `range_too_large` | Range exceeds 31 days; split it into multiple queries |
| 400 | `invalid_tz` | Unknown IANA timezone |
| 400 | `invalid_group_by` | Invalid grouping option |
| 400 | `invalid_scope` | Invalid query scope |
| 400 | `too_many_models` | More than 50 models |
| 401 / 403 | — | Invalid or expired API Key, IP not allowed, or disabled account |
| 429 | — | Exceeds 60 queries per Key per minute, or a global API rate limit |
| 503 | `usage_unavailable` | Usage data is temporarily unavailable; retry later |

> [!WARNING]
>
> A `503 usage_unavailable` response returns no amounts. It means the query is unavailable, not that spending is zero. Do not convert failed responses into zero amounts or overwrite a previous successful result.

## Comparison with other endpoints

| Endpoint | Capability |
| - | - |
| `GET /v1/dashboard/billing/usage` | Cumulative spending only; no model or time filters |
| `POST /v1/logs/export` | Asynchronous export of call details (CSV / XLSX); aggregate them yourself |
| `GET /v1/usage` | Query by time and model; directly returns totals and grouped spending |

For remaining quota, use [Query Token Balance](https://gccai.heqingsong.uk/en/api-reference/account/token-balance.md) or [Query User Balance](https://gccai.heqingsong.uk/en/api-reference/account/user-balance.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.