关于 openrouter-analytics-query
openrouter-analytics-query 是一项用于构造并执行 OpenRouter 分析查询的技能,面向需要检查 API 用量、成本或性能数据的用户。它涵盖查询参数、分类器维度与筛选,以及可输出 JSON 的命令行脚本。
主要功能
- 01按指标与维度构造查询
- 02设置时间粒度、范围和筛选条件
- 03支持分类器维度与筛选
- 04提供命令行查询参数
- 05以 JSON 返回结果与元数据
适用场景
- 01按模型汇总请求量或成本
- 02筛选特定模型或提供商的数据
- 03查看指标的时间序列变化
- 04检查结果是否因行数限制而截断
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ openrouterteam/ skills --skill openrouter-analytics-query安装后在 Claude Code 中输入/openrouter-analytics-query确认已加载。
附带文件README.md
详细介绍
OpenRouter 分析查询执行
针对 OpenRouter API 构建和执行分析查询的完整参考。
前置条件
OPENROUTER_API_KEY必须设置为管理密钥。管理密钥与常规 API 密钥分开 — 可前往 https://openrouter.ai/settings/management-keys 获取
查询端点
POST https://openrouter.ai/api/v1/analytics/query
Authorization: Bearer sk-or-v1-...
Content-Type: application/json
也可以通过 openrouter-analytics 技能脚本执行:
cd <openrouter-analytics-skill-path>/scripts && npx tsx query-analytics.ts --metrics request_count
权威来源(避免信息偏差): 以下指标/维度名称和请求架构仅供说明。实时权威列表来自 meta 端点 — 调用
GET /api/v1/analytics/meta(或discover-schema.ts),并以其响应为准。对于 Agent 可读取的文档,OpenRouter 发布了llms.txt。如果这些文档与本文中的示例不一致,请优先参考它们。
请求架构
{
"metrics": ["request_count", "total_usage"],
"dimensions": ["model"],
"granularity": "day",
"time_range": {
"start": "2026-05-01T00:00:00Z",
"end": "2026-05-20T00:00:00Z"
},
"filters": [
{ "field": "model", "operator": "eq", "value": "anthropic/claude-sonnet-4" }
],
"order_by": { "field": "total_usage", "direction": "desc" },
"limit": 100,
"group_limit": 20,
"classifier_dimensions": {
"classifier_id": "<uuid>",
"dimension_names": ["category"],
"include_nulls": false
},
"classifier_filters": {
"classifier_id": "<uuid>",
"filters": [
{ "field": "sentiment", "operator": "eq", "value": "positive" }
]
}
}
必填字段
| 字段 | 类型 | 描述 |
|---|---|---|
metrics | string[] | 至少一个要计算的指标。调用 meta 端点查看可用指标。 |
可选字段
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
dimensions | string[] | [] | 最多按 2 个维度分组 |
granularity | string | 无 | 时间分桶:minute、hour、day、week、month |
time_range | object | 最近 7 天 | { start, end },使用 ISO 8601 UTC 日期时间字符串。必须包含秒(YYYY-MM-DDTHH:MM:SSZ;允许小数秒)— 分钟精度的值(如 2026-05-01T00:00Z)会被拒绝,并返回 400。 |
filters | object[] | [] | 最多 20 个筛选条件 |
order_by | object | 时间降序(如果设置了粒度) | { field, direction },其中 field 为指标、维度或 "date"(短格式别名 — 根据粒度映射为 date__day、date__hour 等) |
limit | integer | 1000 | 返回的最大总行数(1–10,000)。对于包含维度但未显式设置 group_limit 的时间序列查询,服务可能会提高此值,以容纳预期的时间分桶/维度组合数。 |
group_limit | integer | 自动计算 | 每个不同维度组合的最大行数(ClickHouse LIMIT n BY)。对于未设置此值的时间序列查询(包含粒度和维度),系统会根据时间范围自动计算,以保证每个组覆盖完整时间窗口。显式设置的值会覆盖默认值。未指定维度时忽略。 |
classifier_dimensions | object | 无 | 按动态分类器生成的维度分组。请参阅下文的分类器维度。 |
classifier_filters | object | 无 | 按分类器生成的维度值筛选。请参阅下文的分类器筛选条件。 |
筛选对象结构
{ "field": "<dimension_name>", "operator": "<op>", "value": "<value>" }
- 标量运算符(
eq、neq、gt、gte、lt、lte):value为字符串或数字 - 数组运算符(
in、not_in):value为字符串或数字数组 in/not_in可选接受include_unset: true,此设置也会匹配维度无值的行。仅支持带有未设置分桶的维度(api_key_id、app、user)— 否则请求会被拒绝,并返回 400。- 查询结果中的若干维度会解析为标签(以人类可读名称返回),但筛选条件必须使用底层 ID:
api_key_id— 数字 ID(来自生成元数据)或 64 个字符的 SHA-256 哈希(来自GET /api/v1/keys)。查询前会自动将哈希解析为数字 ID。user— Clerk 用户 ID(例如user_abc123),而不是结果中显示的名称/电子邮件地址。workspace— 工作区 UUID,而不是结果中显示的工作区名称。app— 数字应用 ID,而不是应用标题。model— permaslug(例如openai/gpt-4o),而不是显示名称。
- 其他维度(
provider、origin、country、finish_reason、external_user等)不会进行扩充 — 筛选值与结果中返回的内容相匹配。
排序依据
{ "field": "<metric_or_dimension_or_date>", "direction": "asc" | "desc" }
设置 granularity 且未指定 order_by 时,结果按时间降序排列。
分类器维度
分类器维度支持按动态的用户自定义分类标签(例如主题、情感、类别)分组,这些标签由关联到你账户的分类器生成。
{
"classifier_dimensions": {
"classifier_id": "550e8400-e29b-41d4-a716-446655440000",
"dimension_names": ["category"],
"include_nulls": false
}
}
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
classifier_id | string (UUID) | 是 | 分类器的 ID(必须属于调用者的账户) |
dimension_names | string[] | 否 | 要分组的特定维度名称(最多 2 个)。如果省略,则包含所有分类器维度。名称必须是有效标识符(字母、数字、下划线;最多 64 个字符)。 |
include_nulls | boolean | 否 | 为 true 时,结果中包含未分类的行。默认为 false(仅包含已分类的行)。 |
限制:
- 查询时间范围最多为 31 天
- 单个维度名称 → 结果列会以该名称作为别名(例如
category) - 两个维度名称 → 各自成为独立的结果列,按两个值交叉分组结果
- 省略
dimension_names→ 结果使用通用的clf_dimension_name/clf_dimension_value列(每个维度/值对占一行)
分类器筛选条件
分类器筛选条件可将结果限定为符合特定分类值的生成记录。它们可以单独使用,也可以与 classifier_dimensions 搭配使用。
{
"classifier_filters": {
"classifier_id": "550e8400-e29b-41d4-a716-446655440000",
"filters": [
{ "field": "category", "operator": "eq", "value": "billing" },
{ "field": "sentiment", "operator": "in", "value": ["positive", "neutral"] }
]
}
}
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
classifier_id | string (UUID) | 是 | 分类器的 ID(必须属于调用者的账户) |
filters | object[] | 是 | 1–10 个针对分类器维度的筛选条件 |
filters[].field | string | 是 | 要筛选的分类器维度名称 |
filters[].operator | string | 是 | 以下之一:eq、neq、in、not_in(不支持 gt/lt——值为字符串) |
filters[].value | string | string[] | 是 | eq/neq 使用标量值,in/not_in 使用数组 |
限制:
- 查询时间范围最多为 31 天
- 仅支持相等/集合运算符(分类值为字符串,因此有序比较会按字典序进行)
- 所有筛选字段名称都必须是该分类器中配置的维度
响应结构
{
"data": {
"data": [
{ "date__day": "2026-05-19", "model": "anthropic/claude-sonnet-4", "request_count": "1523", "total_usage": 4.27 },
{ "date__day": "2026-05-18", "model": "openai/gpt-4o", "request_count": "892", "total_usage": 2.15 }
],
"metadata": {
"query_time_ms": 142,
"row_count": 2,
"truncated": false
},
"cachedAt": 1747699200000,
"warnings": ["Could not resolve api_key_id hash: abc123..."]
}
}
响应字段
| 字段 | 描述 |
|---|---|
data.data | 结果行数组。每行包含所请求的指标、维度以及 date__<granularity>(设置了粒度时)对应的键。对于带有单个 dimension_name 的 classifier_dimensions 查询,某列会以该名称作为别名(例如 category)。使用两个名称时,每个名称各有一列,行会按这两个维度交叉分组。省略 dimension_names 时,行包含 clf_dimension_name 和 clf_dimension_value 列,每个维度/值对占一行。 |
data.metadata.query_time_ms | 查询执行时间,单位为毫秒 |
data.metadata.row_count | 返回的行数 |
data.metadata.truncated | 如果结果在达到限制时被截断,则为 true |
data.cachedAt | 结果缓存时的 Unix 时间戳(毫秒)。响应由缓存提供时会包含此字段 |
data.warnings | 可选的非致命警告数组(例如无法解析的 api_key_id 哈希)。查询仍会正常执行;这些警告会告知调用方筛选条件解析问题。 |
数值类型: 计数指标(
request_count、tokens_*等)以字符串形式返回("1523")。成本和速率指标(total_usage、cache_hit_rate、延迟、吞吐量)以数字形式返回(4.27)。进行算术运算前,请使用Number()或parseInt()解析计数值。
标签解析: 维度
api_key_id、app、user和workspace在数据行中返回易读标签(密钥名称、应用标题、用户名、工作区名称),而非原始 ID。哨兵值桶会返回标签而非原始值:api_key_id的-1→Chatroom,app的-1→Unknown,最大 UUID 的workspace哨兵值 →Unattributed。model永远不会被重新标注——它始终保持为 permaslug。
CLI 参考
openrouter-analytics 技能中的 query-analytics.ts 脚本接受以下标志:
| 标志 | 描述 | 示例 |
|---|---|---|
--api-key | API 密钥(回退至 OPENROUTER_API_KEY 环境变量) | --api-key sk-or-v1-... |
--metrics | 逗号分隔的指标名称(必填) | --metrics request_count,total_usage |
--dimensions | 逗号分隔的维度名称 | --dimensions model,provider |
--granularity | 时间分桶大小 | --granularity day |
--start | 时间范围起点(ISO 8601 UTC,必须包含秒) | --start 2026-05-01T00:00:00Z |
--end | 时间范围终点(ISO 8601 UTC,必须包含秒) | --end 2026-05-20T00:00:00Z |
--filter-field | 筛选维度名称(第一个筛选条件;见下方说明) | --filter-field model |
--filter-op | 筛选运算符(第一个筛选条件) | --filter-op eq |
--filter-value | 筛选值(in/not_in 时用逗号分隔) | --filter-value anthropic/claude-sonnet-4 |
--filter-field-N | 第 N 个附加筛选条件的维度名称(N = 1–19) | --filter-field-1 provider |
--filter-op-N | 第 N 个附加筛选条件的运算符 | --filter-op-1 eq |
--filter-value-N | 第 N 个附加筛选条件的值 | --filter-value-1 anthropic |
--order-by | 排序字段 | --order-by total_usage |
--order-dir | 排序方向 | --order-dir desc |
--limit | 最大总行数(1–10000) | --limit 100 |
--group-limit | 每种维度组合的最大行数(1–10000)。如果在包含维度的时间序列查询中省略,服务端会自动计算。 | --group-limit 50 |
CLI 会向 stdout 输出一个包含两个键的 JSON 对象:data(结果行)和 metadata:
{
"data": [ { "model": "anthropic/claude-sonnet-4", "total_usage": 4.27 } ],
"metadata": { "query_time_ms": 142, "row_count": 2, "truncated": false }
}
便于人类阅读的统计信息行(行数、查询耗时、截断/缓存标志)仅供终端使用,会写入 stderr。
以编程方式解析输出时,务必检查
metadata.truncated。 如果为true,则结果已受--limit限制,是一个不完整的数据集——在报告总数/排名前,应增大--limit或进行分页。维度api_key_id、user、app和workspace在数据行中已解析为便于人类阅读的名称。
多条件筛选查询: CLI 会根据未带索引的基础标志(--filter-field/--filter-op/--filter-value)以及带索引的 --filter-field-N/--filter-op-N/--filter-value-N 标志,构建一个多元素 filters 数组(条件之间使用 AND 连接)。每个筛选条件都必须提供三个部分(字段、运算符、值);不完整的三元组会被拒绝。最多可有 20 个筛选条件(基础标志加索引 1–19),与 API 上限一致。索引可以不连续(例如,基础标志加 -2、省略 -1 是允许的——间隔会被跳过,而不会被静默丢弃)。对于 model = X AND provider = Y 这样的查询:
npx tsx query-analytics.ts --metrics request_count \
--filter-field model --filter-op eq --filter-value anthropic/claude-sonnet-4 \
--filter-field-1 provider --filter-op-1 eq --filter-value-1 anthropic
标志值注意事项: CLI 的参数解析器会将任何以 -- 开头的标记视为新标志,因此不能通过 CLI 标志传入以 -- 开头的筛选值。维度值(模型 ID、提供商名称等)不会以 -- 开头,因此实际使用中很少会遇到这个问题——但如果需要传入此类值,请改用下方的直接 curl 方式。
直接使用 API(curl)
如果你更倾向于直接调用 API,而不是使用脚本:
curl -X POST https://openrouter.ai/api/v1/analytics/query \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"metrics": ["total_usage", "request_count"],
"dimensions": ["model"],
"granularity": "day",
"time_range": {
"start": "2026-05-13T00:00:00Z",
"end": "2026-05-20T00:00:00Z"
},
"order_by": { "field": "total_usage", "direction": "desc" },
"limit": 10,
"group_limit": 7
}'
查询构建指南
聚合(非时间序列)
省略 granularity,即可针对每种维度组合获取一行聚合结果:
{
"metrics": ["total_usage", "request_count"],
"dimensions": ["model"],
"order_by": { "field": "total_usage", "direction": "desc" },
"limit": 10
}
时间序列(带粒度)
添加 granularity,即可针对每个时间桶获取一行结果(如果设置了维度,则针对每种维度组合分别返回):
{
"metrics": ["request_count"],
"granularity": "day",
"time_range": {
"start": "2026-05-01T00:00:00Z",
"end": "2026-05-20T00:00:00Z"
}
}
筛选查询
使用筛选条件缩小结果范围。多个筛选条件之间使用 AND 连接:
{
"metrics": ["total_usage", "avg_latency"],
"dimensions": ["provider"],
"filters": [
{ "field": "model", "operator": "eq", "value": "anthropic/claude-sonnet-4" }
]
}
多维度查询
最多组合 2 个维度进行交叉制表:
{
"metrics": ["request_count"],
"dimensions": ["model", "provider"],
"order_by": { "field": "request_count", "direction": "desc" },
"limit": 20
}
错误处理
| 状态 | 含义 | 操作 |
|---|---|---|
| 400 | 查询无效(JSON 请求体格式错误、指标名称错误、维度过多、时间范围无效) | 检查 meta 端点以获取有效值。确认时间范围的开始时间 < 结束时间,且两个时间戳都包含秒。最多 2 个维度、20 个筛选条件。可能缓存指标与不支持的维度、筛选条件、分类器或 minute 粒度组合时,也会返回 400。 |
| 401 | API 密钥无效或缺失 | 检查 OPENROUTER_API_KEY 是否设置正确 |
| 403 | 不是管理密钥 | 密钥必须是配置/管理密钥。请在 openrouter.ai/settings/management-keys 创建 |
| 408 | 查询超时 | 缩小时间范围、减少维度,或添加筛选条件以减少扫描的数据量 |
| 429 | 请求受到速率限制(64 RPM) | 等待后重试 |
| 500 | 服务器错误 | 稍后重试 |
时间范围行为
start 和 end 必须是包含秒的 ISO 8601 UTC 时间戳(2026-05-01T00:00:00Z)。允许使用小数秒;查询开始前会拒绝精确到分钟的时间戳和非 UTC 时区偏移。
某些指标/维度组合支持最长 367 天 的时间范围(使用每日粒度),而另一些组合则限制为 31 天。服务器会根据请求的指标和维度自动确定适用范围。
用量细分指标遵循相同规则:credits_usage、usage_upstream、usage_cache、usage_data、usage_web 和 usage_upstream_web 支持最长 367 天;而 openrouter_usage、byok_fees、usage_file、usage_upstream_file、usage_web_fetch 和 usage_upstream_web_fetch 限制为 31 天。
可能缓存指标(possible_cached_tokens、possible_cache_hit_rate、cache_capture_rate)始终读取每小时汇总数据。无论粒度如何,这些指标的时间范围均限制为 31 天,仅支持 model 和 provider 维度及筛选条件;与 minute 粒度、分类器维度或分类器筛选条件组合时会返回 400。
hour 粒度读取分钟级物化视图,因此时间范围上限为 31 天,即使相关指标本身允许 367 天也是如此。
分类器维度和分类器筛选条件始终会将时间范围上限设为 31 天。
如果查询超时,请尝试:
- 缩小时间范围
- 移除延迟/吞吐量指标
- 移除每次生成的维度(
provider、origin、country、finish_reason等) - 移除分类器维度/筛选条件(这些条件的计算开销更大)