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

# 查询消费用量

>  - 查询指定时间范围内的消费金额与调用统计
- 支持按模型过滤、按模型或自然日分组
- 支持当前 API Key 或整个账号的消费统计
- 返回美元金额、积分、调用次数与 token 用量 

使用 API Key 查询指定时间范围内的消费金额，可按模型过滤，并按模型、自然日或二者组合分组。此接口直接返回聚合结果，不需要创建任务或轮询任务状态。

<RequestExample>
  ```bash cURL theme={null}
  curl --get 'https://api.apimart.ai/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://api.apimart.ai/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", "用量查询失败")
      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://api.apimart.ai/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 ?? "用量查询失败"}`,
    );
  }

  console.log(payload.data.total);
  console.log(payload.data.items);
  ```
</RequestExample>

<ResponseExample>
  ```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"
    }
  }
  ```
</ResponseExample>

## 认证

<ParamField header="Authorization" type="string" required>
  使用与调用模型相同的 API Key，通过 Bearer Token 认证。访问 [API Key 管理页面](https://apimart.ai/keys) 获取密钥。

  ```
  Authorization: Bearer YOUR_API_KEY
  ```
</ParamField>

<Info>
  余额为 0 时仍可查询。本接口不校验余额，但仍校验 API Key 状态、过期时间、IP 白名单及账号状态。
</Info>

## 接口端点

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

两个端点功能相同，支持 CORS 跨域请求。请妥善保管 API Key，不要将其暴露在公开的前端代码中。

## 请求参数

所有参数均通过 URL Query 传递。

<ParamField query="start" type="integer | string">
  起始时间，包含该时刻。支持 Unix 秒级时间戳或带时区的 RFC3339 字符串，例如 `2026-09-01T00:00:00+08:00`。

  不传时默认为 `end` 前 24 小时。时间戳单位为秒，不是毫秒。
</ParamField>

<ParamField query="end" type="integer | string">
  结束时间，不包含该时刻。格式与 `start` 相同，不传时默认为当前时间。

  必须晚于 `start`，且 `end - start` 不得超过 31 天。
</ParamField>

<ParamField query="model" type="string">
  模型名称，不传时统计全部模型。多个模型使用英文逗号分隔，最多 `50` 个。

  精确匹配、不区分大小写，不支持通配符。

  示例：`gpt-5.6-luna,sora-2`
</ParamField>

<ParamField query="group_by" type="string" default="none">
  分组方式：

  * `none`：仅返回合计，`items` 为空数组
  * `model`：按模型分组
  * `date`：按自然日分组
  * `model,date`：按模型和自然日组合分组
</ParamField>

<ParamField query="tz" type="string" default="Asia/Shanghai">
  IANA 时区名称，默认 `Asia/Shanghai`。

  仅影响 `group_by` 包含 `date` 时的自然日边界，不改变查询的起止时刻。RFC3339 起止时间仍按其自身携带的时区解析。
</ParamField>

<ParamField query="scope" type="string" default="key">
  统计范围：

  * `key`：仅统计当前 API Key（默认）
  * `account`：统计当前 API Key 所属账号的全部 API Key 合计
</ParamField>

<Note>
  查询时间区间为 `[start, end)`：包含起点、不包含终点。相邻查询以相同的时间作为前一次的 `end` 和后一次的 `start`，不会重复计算边界时刻。

  手动拼接 URL 时，RFC3339 中的 `+` 必须编码为 `%2B`。示例中的 cURL `--data-urlencode`、Python `params` 和 JavaScript `URLSearchParams` 会自动处理编码。
</Note>

## 请求示例

### 当前 API Key 最近 24 小时的消费合计

不传 Query 参数即可使用默认时间范围、默认统计范围和默认分组方式：

```bash theme={null}
curl 'https://api.apimart.ai/v1/usage' \
  --header 'Authorization: Bearer <token>'
```

### 整个账号指定模型的每日消费

查询 2026 年 9 月 11 日至 9 月 18 日（北京时间，不含 9 月 18 日）的消费：

```bash theme={null}
curl --get 'https://api.apimart.ai/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'
```

### 按模型和自然日组合分组

```bash theme={null}
curl --get 'https://api.apimart.ai/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'
```

该分组方式下，每个 `items` 元素同时包含 `model` 和 `date`。

## 响应字段

<ResponseField name="success" type="boolean">
  查询是否成功。成功时为 `true`，用量查询错误时为 `false`。
</ResponseField>

<ResponseField name="data" type="object">
  成功时返回查询范围、合计与分组明细。

  <Expandable title="data 属性">
    <ResponseField name="scope" type="string">
      本次统计范围：`key` 或 `account`。
    </ResponseField>

    <ResponseField name="start" type="integer">
      实际查询起始时间，Unix 秒级时间戳，含起点。
    </ResponseField>

    <ResponseField name="end" type="integer">
      实际查询结束时间，Unix 秒级时间戳，不含终点。
    </ResponseField>

    <ResponseField name="tz" type="string">
      本次使用的自然日分组时区。
    </ResponseField>

    <ResponseField name="group_by" type="string">
      本次分组方式：`none`、`model`、`date` 或 `model,date`。
    </ResponseField>

    <ResponseField name="total" type="object">
      本次查询范围内的合计，统计字段见下表。
    </ResponseField>

    <ResponseField name="items" type="object[]">
      分组明细，按 `amount_usd` 降序排列；`group_by=none` 时为空数组。每个元素包含下表中的统计字段。

      * `group_by` 包含 `model` 时，元素包含 `model`
      * `group_by` 包含 `date` 时，元素包含 `date`，格式为 `YYYY-MM-DD`，按 `tz` 划分自然日
    </ResponseField>
  </Expandable>
</ResponseField>

`data.total` 与 `data.items[]` 共用以下统计字段：

| 字段                  | 类型      | 说明                                  |
| ------------------- | ------- | ----------------------------------- |
| `amount_usd`        | number  | 美元金额，保留 6 位小数                       |
| `credits`           | number  | 站内积分，等于 `amount_usd × 10`，与官网展示单位一致 |
| `requests`          | integer | 计费成功的调用次数                           |
| `prompt_tokens`     | integer | 输入 token 数；按次或按秒计费的图片、视频模型通常为 0     |
| `completion_tokens` | integer | 输出 token 数；按次或按秒计费的图片、视频模型通常为 0     |

<ResponseField name="error" type="object">
  用量查询错误时返回，包含 `code`、`message` 和 `type`，其中 `type` 为 `usage_query_error`。401 / 403 鉴权错误由鉴权层返回。
</ResponseField>

## 限流与缓存

* 每把 API Key 每分钟最多查询 `60` 次，同时受全局 API 限流约束
* 相同参数的查询结果缓存 `60` 秒，响应头 `X-Usage-Cache` 为 `hit` 或 `miss`
* 通常 1 秒内可查到消费记录，但最近 1 分钟的数据可能不完整，且存在缓存延迟
* 建议查询间隔不低于 1 分钟，不要将本接口作为实时扣费通知

## 统计口径

* 数据来自计费成功的调用记录，与官网“数据看板”使用相同数据
* 调用失败或任务失败后退款的记录不计入，无需自行冲抵；组图部分成功时按实际交付张数计费
* 按计费落账时刻归属消费；异步图片、视频任务在完成时落账，不是提交时刻。跨零点任务归入完成当天
* 删除后重建的 API Key 属于新的 Key；使用新 Key 查询 `scope=key` 时，不包含旧 Key 的历史
* 后台人工调整余额不属于调用消费，不在统计范围内
* 可查询 2026 年 4 月 27 日之后的数据

## 错误处理

| HTTP 状态码  | `error.code`                    | 说明                               |
| --------- | ------------------------------- | -------------------------------- |
| 400       | `invalid_start` / `invalid_end` | 起止时间格式无效                         |
| 400       | `invalid_range`                 | `end` 不大于 `start`                |
| 400       | `range_too_large`               | 时间跨度超过 31 天，请拆分为多个查询区间           |
| 400       | `invalid_tz`                    | 未知的 IANA 时区                      |
| 400       | `invalid_group_by`              | 分组方式无效                           |
| 400       | `invalid_scope`                 | 统计范围无效                           |
| 400       | `too_many_models`               | 模型数量超过 50 个                      |
| 401 / 403 | —                               | API Key 无效、过期、IP 不在白名单或账号被停用     |
| 429       | —                               | 超过每 Key 每分钟 60 次的限制，或触发全局 API 限流 |
| 503       | `usage_unavailable`             | 用量数据暂时不可用，请稍后重试                  |

<Warning>
  收到 `503 usage_unavailable` 时，不会返回任何金额。这表示查询不可用，不表示消费为 0；不要将失败响应转换为零金额或覆盖此前成功查询的结果。
</Warning>

## 与其他接口的区别

| 接口                                | 能力                          |
| --------------------------------- | --------------------------- |
| `GET /v1/dashboard/billing/usage` | 返回累计已用总额，不能按模型或时间筛选         |
| `POST /v1/logs/export`            | 异步导出调用明细（CSV / XLSX），需要自行汇总 |
| `GET /v1/usage`                   | 按指定时间与模型查询，直接返回消费合计及分组明细    |

如需查询剩余额度，请使用 [查询令牌余额](/cn/api-reference/account/token-balance) 或 [查询用户余额](/cn/api-reference/account/user-balance)。
