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

# 接口参考

> Admin Key 可调用的全部十一个接口，含参数、响应与示例。

所有接口的基础地址是 `https://api.ephone.ai`，认证头统一为 `Authorization: Bearer sk-admin-...`。

除两个导出接口外，响应都是 `{"success": bool, "message": string, "data": ...}` 的 JSON 信封。

## 账户

### 查看账户资料

`GET /api/user/self` · 作用域 `account:read`

返回整份账户资料，其中 `balance` 是当前余额。

```bash theme={null}
curl https://api.ephone.ai/api/user/self \
  -H "Authorization: Bearer $ADMIN_KEY"
```

```json theme={null}
{
  "success": true,
  "data": {
    "username": "alice",
    "display_name": "Alice",
    "balance": "128.5",
    "level": "Tier 1",
    "language": "zh",
    "created_at": 1767225600
  }
}
```

响应字段很多，这里只列常用的几项。金额是字符串形式的十进制数，按字符串解析可以避免浮点误差。出于安全考虑，密码、会话凭据、实名证件信息不会出现在响应里。

账户资料里没有累计消费和请求次数。要按时间段查，用下面的「调用统计」和「日志明细列表」。

## 调用日志

> [!TIP]
>
> **怎么查最省资源。** 日志表按创建时间分区，带上时间范围才能触发分区裁剪，
> 只扫那几个分区而不是整张表。所以推荐的用法是**窄窗口轮询**：每次拉最近几分钟
> 到一小时，脚本按固定间隔跑。
>
> 不带时间范围拉全量是代价最高的形态，它没有分区裁剪可用。接口不会拒绝这种请求，
> 但每次查询都有时限（明细列表单次最多 30 秒），超时会直接失败。
> 一次性对账这类场景建议按天或按周分段拉，而不是一次拉整年。

> [!NOTE]
>
> **时间戳用秒或毫秒都可以。** 这一组接口的 `start_timestamp`、`end_timestamp` 会自动识别单位：
> 小于 `100000000000` 的按 Unix 秒处理，否则按毫秒。起止时刻都包含在内，按请求的创建时间筛选。
> 响应里的时间字段一律是毫秒。

这一组接口只看得到消费记录：请求在扣费之前就失败的，不会出现在这里。

### 日志明细列表

`GET /api/log/self` · 作用域 `logs:read`

分页返回调用日志明细，最新的在前。与下面的导出接口是同一批数据的两种格式，这个返回 JSON。

| 参数 | 类型 | 说明 |
| - | - | - |
| `p` | int | 页码，从 1 开始 |
| `page_size` | int | 每页条数，默认 10，上限 1000 |
| `start_timestamp` | int | 起始时间，秒或毫秒 |
| `end_timestamp` | int | 结束时间，秒或毫秒 |
| `model_name` | string | 按模型名筛选，可选 |
| `token_id` | int | 按密钥 ID 筛选，可选，精确匹配；ID 可以从「密钥列表」接口取得 |
| `token_name` | string | 按密钥名筛选，可选，**模糊匹配**：名字里包含这段文字的密钥都算 |
| `vendor_id` | int | 按供应商筛选，可选 |
| `status` | string | 按状态筛选，可选：`SUCCESS`、`FAILURE`，或 `UNFINISHED`（还没结束的异步任务） |
| `skip_count` | bool | 传 `1` 时不计算总条数（`total` 返回 `-1`），翻页拉数据时更快 |

```bash theme={null}
curl -G https://api.ephone.ai/api/log/self \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -d p=1 -d page_size=20 \
  -d start_timestamp=1767225600 \
  -d end_timestamp=1767311999
```

```json theme={null}
{
  "success": true,
  "data": {
    "items": [
      {
        "id": 1,
        "created_at": 1767225612345,
        "completed_at": 1767225614012,
        "model_name": "gpt-4o",
        "token_id": 42,
        "token_name": "生产环境",
        "is_stream": true,
        "status": "SUCCESS",
        "request_id": "a3241aced92f97ac",
        "quota": "0.0123",
        "usage": {
          "prompt_tokens": 1200,
          "completion_tokens": 340,
          "total_tokens": 1540,
          "text_input_tokens": 1200,
          "text_output_tokens": 340
        }
      }
    ],
    "total": 1,
    "page": 1,
    "page_size": 20,
    "has_more": false
  }
}
```

每条日志的字段较多，上面只列常用的几项：

| 字段 | 说明 |
| - | - |
| `id` | 这次查询结果里的序号（1、2、3……），**不是**日志的固定 ID，翻页、换筛选条件都会变。去重请用 `request_id` |
| `request_id` | 这次请求的唯一 ID |
| `created_at`、`completed_at` | 请求开始、结束的时间，毫秒；还没结束的异步任务 `completed_at` 为 `0` |
| `quota` | 这次请求扣的金额，字符串形式的十进制数 |
| `usage` | 用量明细。`prompt_tokens`、`completion_tokens` 沿用 OpenAI 的口径（输入里可能含缓存命中）；`text_input_tokens`、`text_output_tokens`、`text_cache_read_tokens` 等是计费用的拆分。按次计费的请求可能没有这一项 |
| `has_more` | 后面还有没有数据，翻页以它为准 |
| `total` | 符合条件的总条数，可能为 `-1`，见下方说明 |

> [!WARNING]
>
> **`total` 可能是 `-1`。** 总条数是一次单独的计数查询，限时三秒；时间范围很大时可能数不完，
> 这时 `total` 返回 `-1` 表示未知，`items` 照常完整。翻页请看 `has_more`，不要用 `total` 推算页数。
> 只拉数据、不需要总数时带上 `skip_count=1`，每一页都能省掉这次计数；需要总数时用下面的「日志总条数」接口。

### 日志总条数

`GET /api/log/self/count` · 作用域 `logs:read`

数出符合条件的日志条数，也就是一段时间里的请求次数。筛选参数与明细列表相同，计数最多跑 10 秒，
比明细列表里顺带的计数（3 秒）更容易数完。

| 参数 | 类型 | 说明 |
| - | - | - |
| `start_timestamp` | int | 起始时间，秒或毫秒 |
| `end_timestamp` | int | 结束时间，秒或毫秒 |
| `model_name` | string | 按模型名筛选，可选 |
| `token_id` | int | 按密钥 ID 筛选，可选，精确匹配 |
| `token_name` | string | 按密钥名筛选，可选，模糊匹配 |
| `vendor_id` | int | 按供应商筛选，可选 |
| `status` | string | 按状态筛选，可选，取值同明细列表 |

```bash theme={null}
curl -G https://api.ephone.ai/api/log/self/count \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -d token_id=42 \
  -d start_timestamp=1767225600 \
  -d end_timestamp=1767311999
```

```json theme={null}
{
  "success": true,
  "data": { "total": 1530 }
}
```

`total` 为 `-1` 表示 10 秒内没数完。这时把时间范围拆成首尾不重叠的几段分别数，再相加（起止时刻都算在内，相邻两段别共用同一个时刻）。
要按密钥或按小时出一张次数表，用下面「导出用量透视」的 `requests` 列更省事。

### 调用统计

`GET /api/log/self/stat` · 作用域 `logs:read`

返回一段时间内的消费金额，以及最近 60 秒的吞吐。

| 参数 | 类型 | 说明 |
| - | - | - |
| `start_timestamp` | int | 起始时间，秒或毫秒；起止都不传时默认统计当天 |
| `end_timestamp` | int | 结束时间，秒或毫秒 |
| `model_name` | string | 按模型名筛选，可选 |
| `token_id` | int | 按密钥 ID 筛选，可选，精确匹配 |
| `token_name` | string | 按密钥名筛选，可选，模糊匹配 |
| `vendor_id` | int | 按供应商筛选，可选 |
| `skip_rate` | bool | 传 `1` 时不计算 `rpm`、`tpm`、`mpm`（固定返回 `0`），只要金额时更快 |

```bash theme={null}
curl -G https://api.ephone.ai/api/log/self/stat \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -d start_timestamp=1767225600 \
  -d end_timestamp=1769904000 \
  -d model_name=gpt-4o
```

```json theme={null}
{
  "success": true,
  "data": {
    "quota": 12.3456,
    "rpm": 8,
    "tpm": 15420,
    "mpm": 0.42,
    "unfinished_count": 0,
    "unfinished_by_vendor": {}
  }
}
```

| 字段 | 说明 |
| - | - |
| `quota` | 时间段内的消费金额合计 |
| `rpm` | 最近 60 秒内**完成**的请求数，与时间段参数无关 |
| `tpm` | 同一窗口内的 token 数：输入 + 缓存写入 + 输出，不含缓存读取 |
| `mpm` | 同一窗口内的消费金额 |
| `unfinished_count` | 时间段内提交、至今还没结束的异步任务数；`unfinished_by_vendor` 是按供应商 ID 的拆分 |
| `unavailable` | 只在有部分没算出来时出现，见下方说明 |

> [!WARNING]
>
> **用数字之前先看 `unavailable`。** 三部分统计各自限时。某一部分在时限内没算完时，响应仍是 `"success": true`，
> 但会多出 `unavailable` 数组，列出没算出来的部分：`quota`（金额合计）、`rate`（`rpm`、`tpm`、`mpm`）、
> `unfinished`（未结束任务数）。这时对应字段里的 `0` 不是真实值。对账脚本必须检查这个字段，遇到时缩小时间范围再查。

```json theme={null}
{
  "success": true,
  "data": {
    "quota": 0,
    "rpm": 8,
    "tpm": 15420,
    "mpm": 0.42,
    "unfinished_count": 0,
    "unfinished_by_vendor": {},
    "unavailable": ["quota"]
  }
}
```

### 导出日志明细

`GET /api/log/self/stream-export` · 作用域 `logs:read`

流式导出日志明细。

> [!WARNING]
>
> **这个接口直接返回 CSV 正文，不返回下载链接。** 响应头是 `Content-Type: text/csv; charset=utf-8`，内容以流的方式逐行写出，文件开头带 UTF-8 BOM（便于 Excel 正确识别中文）。脚本里把响应体重定向到文件即可，不需要任何二次请求。

| 参数 | 类型 | 说明 |
| - | - | - |
| `start_timestamp` | int | 起始时间，秒或毫秒 |
| `end_timestamp` | int | 结束时间，秒或毫秒 |
| `model_name` | string | 按模型名筛选，可选 |
| `token_id` | int | 按密钥 ID 筛选，可选，精确匹配 |
| `token_name` | string | 按密钥名筛选，可选，模糊匹配 |
| `vendor_id` | int | 按供应商筛选，可选 |
| `status` | string | 按状态筛选，可选，取值同明细列表 |
| `columns` | string | 需要的列，逗号分隔；留空导出全部 |
| `currency` | string | `CNY` 或 `USD`，影响金额列的换算 |

```bash cURL theme={null}
curl -G https://api.ephone.ai/api/log/self/stream-export \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -d start_timestamp=1767225600 \
  -d end_timestamp=1769904000 \
  -d currency=CNY \
  -o logs.csv
```

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

r = requests.get(
    "https://api.ephone.ai/api/log/self/stream-export",
    headers={"Authorization": f"Bearer {ADMIN_KEY}"},
    params={"start_timestamp": 1767225600, "end_timestamp": 1769904000},
    stream=True,
)
r.raise_for_status()
with open("logs.csv", "wb") as f:
    for chunk in r.iter_content(chunk_size=8192):
        f.write(chunk)
```

`columns` 支持的列包括 `created_at`、`model_name`、`token_name`、`prompt_tokens`、`completion_tokens`、`cached_tokens`、`reasoning_tokens`、`quota` 等。列的顺序是固定的，不随 `columns` 里的书写顺序变化，读取时按表头取列。使用缓存、推理或多模态模型时，建议显式导出细分列，否则只看总计会与实际计费对不上。

## 用量透视

### 导出用量透视

`GET /api/data/self/pivot/stream-export` · 作用域 `usage:read`

按维度汇总用量，同样直接返回 CSV 正文。每一行是一个分组，列包括 `requests`（请求次数）、`errors`（失败次数）、`spend`（消费金额）、各类 token 数和 `avg_latency_ms` 等，最多 5000 行。

| 参数 | 类型 | 说明 |
| - | - | - |
| `start_timestamp` | int | 起始时间，**毫秒** |
| `end_timestamp` | int | 结束时间，**毫秒** |
| `group_by` | string | 分组维度：`model`（默认）、`token`、`vendor`、`token_group`、`time` |
| `metric` | string | 行的排序依据，从大到小；默认 `spend`，也可以用 `requests`、`tokens` 等 |
| `currency` | string | `CNY` 或 `USD`（默认），影响金额列 |
| `model_name` | string | 按模型名筛选，可选 |
| `token_id` | int | 按密钥 ID 筛选，可选 |

`group_by=token` 时 `key` 列是密钥 ID；`group_by=time` 时按小时分组，`key` 是该小时起点的 Unix 秒。

> [!NOTE]
>
> 这个接口只认**毫秒**：日志接口秒和毫秒都认，这里不行，传秒会被当成 1970 年，导出的文件只有表头。
>
> 数据按小时汇总，起止时间都按整点算：起点所在的小时算在内，终点如果正好是整点，那一小时不算在内。
> 分段导出时让下一段的起点等于上一段的终点即可，首尾相接不重叠。单次跨度上限约半年（186 天）。
>
> 汇总是定时跑的，最近一小段时间的请求可能还没算进去；要实时的数用日志接口。

```bash theme={null}
curl -G https://api.ephone.ai/api/data/self/pivot/stream-export \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -d start_timestamp=1767225600000 \
  -d end_timestamp=1769904000000 \
  -d group_by=token \
  -d metric=requests \
  -o usage.csv
```

## API 密钥管理

> [!WARNING]
>
> 这一组接口管理的是**调用模型用的 API 密钥**，不是 Admin Key 自身。Admin Key 无法创建、修改或撤销任何 Admin Key，包括它自己。

### 密钥列表

`GET /api/token/` · 作用域 `keys:read`

分页返回 API 密钥列表。响应中的密钥值是掩码，明文任何接口都取不到。

| 参数 | 类型 | 说明 |
| - | - | - |
| `p` | int | 页码，从 1 开始 |
| `page_size` | int | 每页条数 |

```bash theme={null}
curl -G https://api.ephone.ai/api/token/ \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -d p=1 -d page_size=20
```

```json theme={null}
{
  "success": true,
  "data": {
    "items": [
      {
        "id": 42,
        "name": "生产环境",
        "key_format": "sk-ep-",
        "key_mask": "e3Xq**********9f2c",
        "status": 1,
        "remain_quota": "50",
        "unlimited_quota": false,
        "used_quota": "12.5",
        "expired_time": -1,
        "group": "default",
        "created_time": 1767225600
      }
    ],
    "page": 1,
    "page_size": 20,
    "total": 1
  }
}
```

`expired_time` 为 `-1` 表示永不过期。`used_quota` 是这枚密钥累计消费的金额。

### 单枚密钥详情

`GET /api/token/{id}` · 作用域 `keys:read`

返回单枚密钥的完整配置，密钥值同样是掩码。修改密钥之前先用它取回完整配置，见下方「修改密钥」。

```bash theme={null}
curl https://api.ephone.ai/api/token/42 \
  -H "Authorization: Bearer $ADMIN_KEY"
```

### 创建密钥

`POST /api/token/` · 作用域 `keys:write`

创建一枚新的 API 密钥。**明文只在这次响应里出现一次。**

| 字段 | 类型 | 说明 |
| - | - | - |
| `name` | string | 名称，不超过 50 字符 |
| `remain_quota` | number | 额度，`unlimited_quota` 为 `true` 时忽略 |
| `unlimited_quota` | bool | 是否不限额度 |
| `expired_time` | int | 过期时间 Unix 秒，`-1` 为永不过期 |
| `group` | string | 分组，留空使用默认 |

```bash theme={null}
curl -X POST https://api.ephone.ai/api/token/ \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"批处理","remain_quota":10,"expired_time":-1,"group":"default"}'
```

```json theme={null}
{
  "success": true,
  "data": { "id": 43, "key": "sk-ep-新创建的密钥明文" }
}
```

> [!WARNING]
>
> 创建密钥后请立即保存 `key`。系统只存哈希，之后任何接口都无法再取回明文，这一点对 Admin Key 和登录用户同样适用。

### 修改密钥

`PUT /api/token/` · 作用域 `keys:write`

修改已有密钥的配置。请求体需要带 `id`。

> [!WARNING]
>
> **这是整体替换，不是只改你传的那几项。** 请求体里没带的字段会被清成默认值：只传名字和额度的话，
> `expired_time` 会变成 `0`、`unlimited_count` 会变成 `false`，密钥立即无法使用；分组、模型限制、IP 白名单、
> 限流配置也会一并清掉。
>
> 正确做法是先用「单枚密钥详情」取回完整配置，只改需要的字段，再把整个对象发回去。

```bash cURL theme={null}
# 1. 取回完整配置，改需要的字段
curl -s https://api.ephone.ai/api/token/43 \
  -H "Authorization: Bearer $ADMIN_KEY" \
  | jq '.data | .name = "批处理-已调整" | .remain_quota = 20' > token.json

# 2. 整个发回
curl -X PUT https://api.ephone.ai/api/token/ \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d @token.json
```

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

headers = {"Authorization": f"Bearer {ADMIN_KEY}"}
token = requests.get("https://api.ephone.ai/api/token/43", headers=headers).json()["data"]
token["name"] = "批处理-已调整"
token["remain_quota"] = 20
r = requests.put("https://api.ephone.ai/api/token/", headers=headers, json=token)
print(r.json()["success"])
```

取回的配置里 `key`、`key_mask` 是掩码，原样发回即可，不会改动密钥本身。

### 重新生成密钥

`POST /api/token/{id}/rotate` · 作用域 `keys:write`

给一枚密钥换一个新值。**旧值立即失效**，名称、额度、分组、模型限制、IP 白名单等配置全部保留，`id` 不变。新值只在这次响应里出现一次。

适合定期轮换，或怀疑密钥泄露时使用。换之前先确认用到这枚密钥的程序都能马上改配置，换完之后还在用旧值的请求会返回 401。

```bash theme={null}
curl -X POST https://api.ephone.ai/api/token/43/rotate \
  -H "Authorization: Bearer $ADMIN_KEY"
```

```json theme={null}
{
  "success": true,
  "data": { "id": 43, "key": "sk-ep-新生成的密钥明文" }
}
```

> [!WARNING]
>
> 请立即保存新的 `key`。和创建一样，系统只存哈希，之后任何接口都无法再取回明文。

### 删除密钥

`DELETE /api/token/{id}` · 作用域 `keys:write`

删除指定密钥，立即生效。

```bash theme={null}
curl -X DELETE https://api.ephone.ai/api/token/43 \
  -H "Authorization: Bearer $ADMIN_KEY"
```

> [!NOTE]
>
> 批量删除接口不对 Admin Key 开放。需要删多枚请逐个调用，或登录控制台操作。


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