mcpField
O
openrouter-analytics-query

openrouter-analytics-query

github.com/openrouterteam数据与数据库309289 次安装1 天前更新
代码仓库

关于 openrouter-analytics-query

openrouter-analytics-query 是一项用于构造并执行 OpenRouter 分析查询的技能,面向需要检查 API 用量、成本或性能数据的用户。它涵盖查询参数、分类器维度与筛选,以及可输出 JSON 的命令行脚本。

主要功能

  1. 01按指标与维度构造查询
  2. 02设置时间粒度、范围和筛选条件
  3. 03支持分类器维度与筛选
  4. 04提供命令行查询参数
  5. 05以 JSON 返回结果与元数据

适用场景

  1. 01按模型汇总请求量或成本
  2. 02筛选特定模型或提供商的数据
  3. 03查看指标的时间序列变化
  4. 04检查结果是否因行数限制而截断

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/openrouterteam/skills --skill openrouter-analytics-query

安装后在 Claude Code 中输入/openrouter-analytics-query确认已加载。

附带文件README.md

详细介绍

OpenRouter 分析查询执行

针对 OpenRouter API 构建和执行分析查询的完整参考。

前置条件

查询端点

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" }
    ]
  }
}
必填字段
字段类型描述
metricsstring[]至少一个要计算的指标。调用 meta 端点查看可用指标。
可选字段
字段类型默认值描述
dimensionsstring[][]最多按 2 个维度分组
granularitystring无时间分桶:minute、hour、day、week、month
time_rangeobject最近 7 天{ start, end },使用 ISO 8601 UTC 日期时间字符串。必须包含秒(YYYY-MM-DDTHH:MM:SSZ;允许小数秒)— 分钟精度的值(如 2026-05-01T00:00Z)会被拒绝,并返回 400。
filtersobject[][]最多 20 个筛选条件
order_byobject时间降序(如果设置了粒度){ field, direction },其中 field 为指标、维度或 "date"(短格式别名 — 根据粒度映射为 date__day、date__hour 等)
limitinteger1000返回的最大总行数(1–10,000)。对于包含维度但未显式设置 group_limit 的时间序列查询,服务可能会提高此值,以容纳预期的时间分桶/维度组合数。
group_limitinteger自动计算每个不同维度组合的最大行数(ClickHouse LIMIT n BY)。对于未设置此值的时间序列查询(包含粒度和维度),系统会根据时间范围自动计算,以保证每个组覆盖完整时间窗口。显式设置的值会覆盖默认值。未指定维度时忽略。
classifier_dimensionsobject无按动态分类器生成的维度分组。请参阅下文的分类器维度。
classifier_filtersobject无按分类器生成的维度值筛选。请参阅下文的分类器筛选条件。
筛选对象结构
{ "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_idstring (UUID)是分类器的 ID(必须属于调用者的账户)
dimension_namesstring[]否要分组的特定维度名称(最多 2 个)。如果省略,则包含所有分类器维度。名称必须是有效标识符(字母、数字、下划线;最多 64 个字符)。
include_nullsboolean否为 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_idstring (UUID)是分类器的 ID(必须属于调用者的账户)
filtersobject[]是1–10 个针对分类器维度的筛选条件
filters[].fieldstring是要筛选的分类器维度名称
filters[].operatorstring是以下之一:eq、neq、in、not_in(不支持 gt/lt——值为字符串)
filters[].valuestring | 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-keyAPI 密钥(回退至 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。
401API 密钥无效或缺失检查 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 等)
  • 移除分类器维度/筛选条件(这些条件的计算开销更大)

评论

支持 Markdown