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

# Log Query

> Paginated log pull by time and type for calls, consumption, top-ups, and more

## Overview

Fetch business logs visible to the current credential. Covers consumption, top-up, error, refund, admin, and test-credit records — useful for reconciliation, troubleshooting, and usage analytics.

<CardGroup cols={2}>
  <Card title="Max 31 days per request" icon="calendar">
    The span between `startTime` and `endTime` must not exceed 31 days. Time format is always `yyyy-MM-dd HH:mm:ss`.
  </Card>

  <Card title="Pagination defaults" icon="list">
    Defaults: `page=1`, `pageSize=30`. `pageSize` max is 1000.
  </Card>
</CardGroup>

## Endpoint

| Item            | Value                                                               |
| --------------- | ------------------------------------------------------------------- |
| Method          | `GET`                                                               |
| URL             | `https://client.tennda.ai/prod-api/api/logs/openLog`                |
| Auth header     | `Authorization`                                                     |
| Language header | `Accept-Language` (`zh-CN` / `en-US`; affects `billingProcessText`) |

## Authentication

Both header formats are accepted:

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

| Credential                                                          | Visible scope                  | `tokenName`                                               |
| ------------------------------------------------------------------- | ------------------------------ | --------------------------------------------------------- |
| [System access token](https://client.tennda.ai/#/profile?tab=token) | All related logs for that user | Optional; fuzzy match                                     |
| [API Key](/en/interface-module/token-management)                    | Logs for the current Key only  | Ignored; server forces an exact filter on the current Key |

<Warning>
  Never put a full key in URLs, frontend code, logs, or support tickets.
</Warning>

## Request parameters

### Pagination

<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>

### Filters

<ParamField query="tokenName" type="string">
  API Key name. Only effective with system access token auth (fuzzy match); ignored when authenticating with an API Key
</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="types" type="string">
  Log types, comma-separated, e.g. `2,5`
</ParamField>

| `types` value | Meaning     |
| ------------: | ----------- |
|           `1` | Top-up      |
|           `2` | Consumption |
|           `3` | Admin       |
|           `5` | Error       |
|           `6` | Refund      |
|           `8` | Test credit |

### Time range

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

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

<Note>
  `Accept-Language` only affects the language of `billingProcessText`: `zh-CN` / omitted → Chinese, `en-US` → English.
</Note>

## Request examples

<Tabs>
  <Tab title="curl">
    ```bash theme={null}
    curl --get 'https://client.tennda.ai/prod-api/api/logs/openLog' \
      --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://client.tennda.ai/prod-api/api/logs/openLog?${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://client.tennda.ai/prod-api/api/logs/openLog"
    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:", result["data"]["total"])
    for item in result["data"]["rows"]:
        print(item["requestId"], item["modelName"], item["quotaDollar"])
    ```
  </Tab>
</Tabs>

## Success response

```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,
        "cacheTokens": 0,
        "billingProcessText": "Input price: ..., final charge: $0.006098"
      }
    ]
  }
}
```

<Note>
  `quotaDollar` is a decimal string. Parse it with Decimal / BigDecimal — avoid binary floating-point types.
</Note>

### Envelope fields

| Field        | Type    | Description                          |
| ------------ | ------- | ------------------------------------ |
| `code`       | integer | `200` success, `401` auth failure    |
| `msg`        | string  | Status message                       |
| `data.total` | integer | Total matching rows (not page count) |
| `data.rows`  | array   | Current page records                 |

### Log row (common fields)

| Field                   | Type            | Description                                          |
| ----------------------- | --------------- | ---------------------------------------------------- |
| `id`                    | string          | Log ID; treat as a string                            |
| `createdAt`             | integer         | Unix timestamp (seconds)                             |
| `createTime`            | string          | Formatted created time                               |
| `type`                  | integer         | Log type; see table above                            |
| `requestId`             | string \| null  | Request ID                                           |
| `ip`                    | string \| null  | Request IP                                           |
| `requestPath`           | string \| null  | Request path                                         |
| `isStream`              | integer \| null | Whether the call was streaming                       |
| `streamStatus`          | string \| null  | Stream status                                        |
| `useTime`               | integer \| null | Total duration (seconds)                             |
| `firstTokenTime`        | integer \| null | Time to first token (ms)                             |
| `modelName`             | string \| null  | Model name                                           |
| `tokenName`             | string \| null  | Token / Key name                                     |
| `quotaDollar`           | string \| null  | Customer charge (USD)                                |
| `billingType`           | string \| null  | Billing type                                         |
| `billingCountMode`      | string \| null  | Billing count mode                                   |
| `requestConversion`     | string \| null  | Protocol conversion type                             |
| `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                                     |
| `billingProcessText`    | string \| null  | Billing breakdown text (language follows the header) |

<Accordion title="Multimedia and other metering fields">
  | Field                                    | Type            | Description               |
  | ---------------------------------------- | --------------- | ------------------------- |
  | `audioInput` / `audioOutput`             | integer \| null | Audio in/out metering     |
  | `imageInputTokens` / `imageOutputTokens` | integer \| null | Image tokens              |
  | `videoOutputTokens`                      | integer \| null | Video output tokens       |
  | `imageCount`                             | integer \| null | Image count               |
  | `videoResolution`                        | string \| null  | Video resolution          |
  | `toolCallBilling`                        | array \| null   | Tool-call billing details |
</Accordion>

## Error responses

| Scenario                         | `code` | Typical `msg`                             |
| -------------------------------- | -----: | ----------------------------------------- |
| Missing or invalid Authorization |  `401` | `Authorization header missing or invalid` |
| Empty key                        |  `401` | `Authorization key is empty`              |
| Invalid or disabled key          |  `401` | `无效或已禁用的密钥`                               |
| Bad time format                  |  `500` | `startTime 格式错误，请使用 yyyy-MM-dd HH:mm:ss`  |
| Time range too large             |  `500` | `时间范围不能超过1个月`                             |

## Integration tips

1. Keep credentials on the server; never log full keys in application logs.
2. Keep each query within 31 days; page through longer history in segments.
3. Derive page count as `ceil(total / pageSize)`; do not treat `total` as a page number.
4. Check response body `code`; HTTP 200 alone does not mean business success.
5. Parse amount fields as decimal strings; do not recompute with `float` / `number`.
