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

# Log Query

> Paginated query for API call logs, consumption logs, top-up logs, and more

<Info>
  Paginated query for call, consumption, top-up, admin, error, refund, and test-credit logs within the scope of the current credential.
</Info>

## Endpoint

* **HTTP method**: `GET`
* **URL**: `https://maas.gravitex.ai/prod-api/api/logs/v2/page`
* **Auth header**: `Authorization`
* **Language header**: `Accept-Language`; supports `zh-CN`, `en-US`
* **Time format**: `yyyy-MM-dd HH:mm:ss`
* **Max time range**: 31 days
* **Default pagination**: `page=1`, `pageSize=30`
* **Max page size**: 1000

## Authentication

All of the following formats are supported:

```http theme={null}
Authorization: Bearer sk-your_api_key
Authorization: sk-your_api_key
```

| Credential                                                          | Query scope                                         | `tokenName` behavior                                                                     |
| ------------------------------------------------------------------- | --------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| [System access token](https://maas.gravitex.ai/#/profile?tab=token) | Logs for that user                                  | Uses request `tokenName` with fuzzy match                                                |
| [API Key](/cn/interface-module/token-management)                    | Logs for that user belonging to the current API Key | Server forces an exact match on the current API Key name; request `tokenName` is ignored |

<Warning>
  Do not log full keys in URLs, frontend code, logs, or support tickets.
</Warning>

## Query parameters

<ParamField query="page" type="integer" default="1">
  Page number; values ≤ 0 are treated as 1
</ParamField>

<ParamField query="pageSize" type="integer" default="30">
  Page size; values ≤ 0 are treated as 30; max 1000
</ParamField>

<ParamField query="tokenName" type="string">
  API key name. Fuzzy match when authenticated with a [system access token](https://maas.gravitex.ai/#/profile?tab=token); unavailable for [API key](/cn/interface-module/token-management) auth — the server always returns logs for the current API key only
</ParamField>

<ParamField query="modelName" type="string">
  Model name, exact match; comma-separated for multiple models
</ParamField>

<ParamField query="requestId" type="string">
  Request ID, exact match
</ParamField>

<ParamField query="ip" type="string">
  Request IP, exact match
</ParamField>

<ParamField query="useTimeMin" type="integer">
  Minimum duration in seconds, inclusive
</ParamField>

<ParamField query="useTimeMax" type="integer">
  Maximum duration in seconds, inclusive
</ParamField>

<ParamField query="startTime" type="string">
  Start time, format `yyyy-MM-dd HH:mm:ss`, inclusive
</ParamField>

<ParamField query="endTime" type="string">
  End time, format `yyyy-MM-dd HH:mm:ss`, inclusive
</ParamField>

<ParamField query="types" type="string">
  Log types, comma-separated; allowed values: `1,2,3,5,6,8`
</ParamField>

### Log types

| Value | Type        |
| ----: | ----------- |
|   `1` | Top-up      |
|   `2` | Consumption |
|   `3` | Admin       |
|   `5` | Error       |
|   `6` | Refund      |
|   `8` | Test credit |

## Accept-Language

Affects only `billingProcessText`:

| Header                   | Language |
| ------------------------ | -------- |
| `Accept-Language: zh-CN` | Chinese  |
| `Accept-Language: en-US` | English  |
| Omitted or other values  | Chinese  |

## Request examples

<Tabs>
  <Tab title="curl">
    ```bash theme={null}
    curl --get 'https://maas.gravitex.ai/prod-api/api/logs/v2/page' \
      --header 'Authorization: Bearer your_api_key' \
      --header 'Accept-Language: en-US' \
      --data-urlencode 'page=1' \
      --data-urlencode 'pageSize=30' \
      --data-urlencode 'startTime=2026-07-01 00:00:00' \
      --data-urlencode 'endTime=2026-07-21 23:59:59' \
      --data-urlencode 'types=2,5'
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    const params = new URLSearchParams({
      page: '1',
      pageSize: '30',
      startTime: '2026-07-01 00:00:00',
      endTime: '2026-07-21 23:59:59',
      types: '2,5',
    });

    const response = await fetch(
      `https://maas.gravitex.ai/prod-api/api/logs/v2/page?${params}`,
      {
        method: 'GET',
        headers: {
          Authorization: 'Bearer your_api_key',
          'Accept-Language': 'en-US',
        },
      },
    );

    const result = await response.json();
    if (result.code !== 200) {
      throw new Error(result.msg);
    }

    console.log(result.data.total, result.data.rows);
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests

    url = "https://maas.gravitex.ai/prod-api/api/logs/v2/page"
    headers = {
        "Authorization": "Bearer your_api_key",
        "Accept-Language": "en-US",
    }
    params = {
        "page": 1,
        "pageSize": 30,
        "startTime": "2026-07-01 00:00:00",
        "endTime": "2026-07-21 23:59:59",
        "types": "2,5",
    }

    response = requests.get(url, headers=headers, params=params, timeout=30)
    response.raise_for_status()
    result = response.json()

    if result.get("code") != 200:
        raise RuntimeError(result.get("msg"))

    print("Total records:", result["data"]["total"])
    for item in result["data"]["rows"]:
        print(item["requestId"], item["modelName"], item["quotaDollar"])
    ```
  </Tab>
</Tabs>

## Response structure

```json theme={null}
{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "total": 1,
    "rows": [
      {
        "id": "7485162150730129409",
        "createdAt": 1784601721,
        "createTime": "2026-07-21 10:42:01",
        "type": 2,
        "requestId": "request_example_001",
        "ip": "203.0.113.10",
        "requestPath": "/v1/messages",
        "isStream": 1,
        "streamStatus": "正常 (eof)",
        "useTime": 2,
        "firstTokenTime": 1043,
        "modelName": "claude-sonnet-5",
        "tokenName": "default",
        "quotaDollar": "0.006098",
        "billingType": "token_ratio",
        "billingCountMode": "上游返回",
        "requestConversion": "Claude Messages",
        "textInputTokens": 2804,
        "textOutputTokens": 49,
        "cacheCreationTokens5m": null,
        "cacheCreationTokens1h": null,
        "cacheTokens": 0,
        "audioInput": null,
        "audioOutput": null,
        "imageInputTokens": null,
        "imageOutputTokens": null,
        "videoOutputTokens": null,
        "requestedSeconds": null,
        "imageCount": null,
        "videoResolution": null,
        "videoAudio": null,
        "videoHasInputVideo": null,
        "toolCallBilling": null,
        "billingProcessText": "Input price: ..., final cost: $0.006098"
      }
    ]
  }
}
```

<Note>
  `quotaDollar` is returned as a decimal string. Use Decimal/BigDecimal; avoid binary floating-point.
</Note>

## Response fields

| Field                   | Type         | Description                             |
| ----------------------- | ------------ | --------------------------------------- |
| `code`                  | integer      | `200` = success, `401` = auth failure   |
| `msg`                   | string       | Message                                 |
| `data.total`            | integer      | Total matching records (not page count) |
| `data.rows`             | array        | Current page rows                       |
| `id`                    | string/long  | Log ID; treat as string on the client   |
| `createdAt`             | integer      | Unix timestamp in seconds               |
| `createTime`            | string       | Formatted creation time                 |
| `type`                  | integer      | Log type                                |
| `requestId`             | string/null  | Request ID                              |
| `ip`                    | string/null  | Request IP                              |
| `requestPath`           | string/null  | Request path                            |
| `isStream`              | integer/null | Whether streaming                       |
| `streamStatus`          | string/null  | Stream status                           |
| `useTime`               | integer/null | Total duration in seconds               |
| `firstTokenTime`        | integer/null | Time to first token in ms               |
| `modelName`             | string/null  | Model name                              |
| `tokenName`             | string/null  | Token name                              |
| `quotaDollar`           | decimal/null | Customer charge in USD                  |
| `billingType`           | string/null  | Billing type                            |
| `billingCountMode`      | string/null  | Billing count mode                      |
| `requestConversion`     | string/null  | Request protocol conversion             |
| `textInputTokens`       | integer/null | Text input tokens                       |
| `textOutputTokens`      | integer/null | Text output tokens                      |
| `cacheCreationTokens5m` | integer/null | 5-minute cache creation tokens          |
| `cacheCreationTokens1h` | integer/null | 1-hour cache creation tokens            |
| `cacheTokens`           | integer/null | Cache hit tokens                        |
| `audioInput`            | integer/null | Audio input metering                    |
| `audioOutput`           | integer/null | Audio output metering                   |
| `imageInputTokens`      | integer/null | Image input tokens                      |
| `imageOutputTokens`     | integer/null | Image output tokens                     |
| `videoOutputTokens`     | integer/null | Video output tokens                     |
| `requestedSeconds`      | integer/null | Requested duration in seconds           |
| `imageCount`            | integer/null | Image count                             |
| `videoResolution`       | string/null  | Video resolution                        |
| `videoAudio`            | boolean/null | Whether audio is output                 |
| `videoHasInputVideo`    | boolean/null | Whether input video is included         |
| `toolCallBilling`       | array/null   | Tool call billing details               |
| `billingProcessText`    | string/null  | Billing breakdown per `Accept-Language` |

## Error responses

<Tabs>
  <Tab title="Missing or invalid Authorization">
    ```json theme={null}
    {
      "code": 401,
      "msg": "Authorization header missing or invalid",
      "data": null
    }
    ```
  </Tab>

  <Tab title="Empty key">
    ```json theme={null}
    {
      "code": 401,
      "msg": "Authorization key is empty",
      "data": null
    }
    ```
  </Tab>

  <Tab title="Invalid or disabled key">
    ```json theme={null}
    {
      "code": 401,
      "msg": "无效或已禁用的密钥",
      "data": null
    }
    ```
  </Tab>

  <Tab title="Invalid time format">
    ```json theme={null}
    {
      "code": 500,
      "msg": "startTime 格式错误，请使用 yyyy-MM-dd HH:mm:ss",
      "data": null
    }
    ```
  </Tab>

  <Tab title="Range exceeds 31 days">
    ```json theme={null}
    {
      "code": 500,
      "msg": "时间范围不能超过1个月",
      "data": null
    }
    ```
  </Tab>
</Tabs>

## Recommendations

1. Store access tokens or API keys securely on the server; never log full keys.
2. Prefer a time range of at most 31 days.
3. Read `data.total` when paging — do not treat it as a page count.
4. Check response body `code`; do not rely on HTTP 200 alone.
5. Handle amounts with Decimal/BigDecimal; do not recompute with binary floats.
