发布者用量分析
curl --request GET \
--url https://api-datahub.bazhuayu.com/v1/publisher/usageimport requests
url = "https://api-datahub.bazhuayu.com/v1/publisher/usage"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api-datahub.bazhuayu.com/v1/publisher/usage', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const options = {method: 'GET'};
fetch('https://api-datahub.bazhuayu.com/v1/publisher/usage', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api-datahub.bazhuayu.com/v1/publisher/usage"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-datahub.bazhuayu.com/v1/publisher/usage")
.asString();<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-datahub.bazhuayu.com/v1/publisher/usage",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}require 'uri'
require 'net/http'
url = URI("https://api-datahub.bazhuayu.com/v1/publisher/usage")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_bodyusing RestSharp;
var options = new RestClientOptions("https://api-datahub.bazhuayu.com/v1/publisher/usage");
var client = new RestClient(options);
var request = new RestRequest("");
var response = await client.GetAsync(request);
Console.WriteLine("{0}", response.Content);
val client = OkHttpClient()
val request = Request.Builder()
.url("https://api-datahub.bazhuayu.com/v1/publisher/usage")
.get()
.build()
val response = client.newCall(request).execute()false{
"range": {
"created_from": "<string>",
"created_to": "<string>",
"tz_offset": 123
},
"currency": "<string>",
"totals": {
"runs": 123,
"succeeded": 123,
"partial": 123,
"failed": 123,
"cancelled": 123,
"success_rate": 123,
"records": 123,
"avg_duration_ms": 123,
"amount": 123,
"apps_active": 123,
"callers": 123
},
"previous_totals": {
"runs": 123,
"succeeded": 123,
"partial": 123,
"failed": 123,
"cancelled": 123,
"success_rate": 123,
"records": 123,
"avg_duration_ms": 123,
"amount": 123,
"apps_active": 123,
"callers": 123
},
"group_by": "<string>",
"groups": [
{
"runs": 123,
"succeeded": 123,
"partial": 123,
"failed": 123,
"cancelled": 123,
"success_rate": 123,
"records": 123,
"avg_duration_ms": 123,
"amount": 123,
"day": "<string>",
"hour": "<string>",
"namespace": "<string>",
"app_name": "<string>",
"channel": "<string>",
"state": "<string>",
"version": "<string>",
"error_code": "<string>",
"error_category": "<string>",
"sample_message": "<string>",
"last_seen_at": "<string>",
"username": "<string>",
"caller_kind": "<string>"
}
]
}发布与运营
发布者用量分析
我发布的 App 在一段时间内被怎样调用:合计与按日、小时、App、渠道、状态、版本、错误码或调用方拆分。
GET
/
v1
/
publisher
/
usage
发布者用量分析
curl --request GET \
--url https://api-datahub.bazhuayu.com/v1/publisher/usageimport requests
url = "https://api-datahub.bazhuayu.com/v1/publisher/usage"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api-datahub.bazhuayu.com/v1/publisher/usage', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const options = {method: 'GET'};
fetch('https://api-datahub.bazhuayu.com/v1/publisher/usage', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api-datahub.bazhuayu.com/v1/publisher/usage"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-datahub.bazhuayu.com/v1/publisher/usage")
.asString();<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-datahub.bazhuayu.com/v1/publisher/usage",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}require 'uri'
require 'net/http'
url = URI("https://api-datahub.bazhuayu.com/v1/publisher/usage")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_bodyusing RestSharp;
var options = new RestClientOptions("https://api-datahub.bazhuayu.com/v1/publisher/usage");
var client = new RestClient(options);
var request = new RestRequest("");
var response = await client.GetAsync(request);
Console.WriteLine("{0}", response.Content);
val client = OkHttpClient()
val request = Request.Builder()
.url("https://api-datahub.bazhuayu.com/v1/publisher/usage")
.get()
.build()
val response = client.newCall(request).execute()false{
"range": {
"created_from": "<string>",
"created_to": "<string>",
"tz_offset": 123
},
"currency": "<string>",
"totals": {
"runs": 123,
"succeeded": 123,
"partial": 123,
"failed": 123,
"cancelled": 123,
"success_rate": 123,
"records": 123,
"avg_duration_ms": 123,
"amount": 123,
"apps_active": 123,
"callers": 123
},
"previous_totals": {
"runs": 123,
"succeeded": 123,
"partial": 123,
"failed": 123,
"cancelled": 123,
"success_rate": 123,
"records": 123,
"avg_duration_ms": 123,
"amount": 123,
"apps_active": 123,
"callers": 123
},
"group_by": "<string>",
"groups": [
{
"runs": 123,
"succeeded": 123,
"partial": 123,
"failed": 123,
"cancelled": 123,
"success_rate": 123,
"records": 123,
"avg_duration_ms": 123,
"amount": 123,
"day": "<string>",
"hour": "<string>",
"namespace": "<string>",
"app_name": "<string>",
"channel": "<string>",
"state": "<string>",
"version": "<string>",
"error_code": "<string>",
"error_category": "<string>",
"sample_message": "<string>",
"last_seen_at": "<string>",
"username": "<string>",
"caller_kind": "<string>"
}
]
}端点
GET https://api-datahub.bazhuayu.com/v1/publisher/usage
Authorization: Bearer <API Key>)。
我的 App 在一段时间内被怎样调用:区间合计,加按日(或短区间按小时)、按 App、按调用渠道拆分(可两两交叉),或为诊断而按终态、按版本、按错误码拆分。它是账单聚合在发布者侧的对应物:词汇相同(created_from / created_to 按运行发起时间,起点包含、终点不包含;tz_offset 只移动日边界;data_app / triggered_by 缩小范围),归属从「我发起的运行」翻转为「我拥有的 App」(含零 Release 的 App)。
日 / 小时 / App / 渠道拆分来自终态时累加的小时桶,任意区间与整小时偏移都精确且廉价。状态 / 版本 / 错误码拆分按需从运行明细计算,因此必须给出两端且跨度不超过 92 天(400 range-too-wide);错误分组只覆盖带错误的运行,每组附最近一条错误消息 sample_message。作者调试运行默认排除,平台巡检永不计入。成功计入部分成功,取消不进成功率分母,没有终态运行的指标为 null。amount 是调用方为这些运行支付的数据费,不是发布者的结算收益。
日 / 小时分组升序(hour 键是 tz_offset 下的本地时钟 YYYY-MM-DDTHH:00,不带时区后缀),其他分组按运行数降序。data_app 里未知或他人的 App 为 404。
totals.callers 是区间内的不同调用用户数,来自运行明细,只在区间有界且不超过 92 天时有值。group_by=caller 把单个私有或分享 App 按调用方拆分:作者自己(caller_kind=owner)和当前名单内的用户(grantee)按当前用户名显示,其他人(曾被授权者、公开时期的调用者)合并为一个 other 组。公开 App 或多个 App 为 400 caller-group-unavailable:公开 App 的调用方匿名,只计数。
请求
查询参数
string
默认值:"day"
一到两个维度,逗号分隔,取值
day / hour / data_app / triggered_by / state / version / error / caller(如 day,data_app)。day 与 hour 不能组合;state / version / error / caller 需要不超过 92 天的有界区间;caller 还需要恰好一个私有或分享 App。默认 day。string[]
只看这些 App(
<username>/<app_name>,可重复传),默认全部我的 App。string
起点,包含。
string
终点,不包含。
integer
默认值:"0"
日 / 小时分桶的时区偏移,分钟,北京时间传
480。桶是小时级,半小时偏移会近似到整点。范围 -720 到 840。string
只看一个调用渠道(
api / sdk / mcp / web 等)。boolean
默认值:"False"
是否并入作者调试运行。
boolean
默认值:"False"
同时返回紧邻
created_from 之前等长区间的 previous_totals,需要两端都给。示例请求
curl \
-H "Authorization: Bearer $BAZHUAYU_API_KEY" \
"https://api-datahub.bazhuayu.com/v1/publisher/usage?group_by=day,data_app&created_from=2026-09-01T00:00:00%2B08:00&created_to=2026-10-01T00:00:00%2B08:00&tz_offset=480"
响应
200 成功
{
"data": {
"range": {
"created_from": null,
"created_to": null,
"tz_offset": 480
},
"currency": "CNY",
"totals": {
"runs": 2,
"succeeded": 2,
"partial": 0,
"failed": 0,
"cancelled": 0,
"success_rate": 1.0,
"records": 40,
"avg_duration_ms": 422,
"amount": 0.04,
"apps_active": 1,
"callers": null
},
"previous_totals": null,
"group_by": "day",
"groups": [
{
"runs": 2,
"succeeded": 2,
"partial": 0,
"failed": 0,
"cancelled": 0,
"success_rate": 1.0,
"records": 40,
"avg_duration_ms": 422,
"amount": 0.04,
"day": "2026-09-15",
"hour": null,
"namespace": null,
"app_name": null,
"channel": null,
"state": null,
"version": null,
"error_code": null,
"error_category": null,
"sample_message": null,
"last_seen_at": null,
"username": null,
"caller_kind": null
}
]
}
}
data 字段中,其内容如下。
string
币种。
object
必填
object
string
本次实际使用的维度。
object[]
分组列表,每组带与
totals 相同的指标,外加本维度的键(day / hour / namespace + app_name / channel / state / version / error_code + error_category + sample_message + last_seen_at / username + caller_kind),未用到的键为 null。显示 字段
显示 字段
integer
—
integer
—
integer
—
integer
—
integer
—
number
—
integer
—
integer
—
number
—
string
—
string
—
string
—
string
—
string
—
string
—
string
version dimension: the Release version the run was pinned to; null for debug runs (they pin a Build snapshot)
string
—
string
—
string
error dimension: message of the most recent run in this group
string
—
string
caller dimension: the caller’s current username; null for the merged
other group or when the user has no usernamestring
caller dimension:
owner (the publisher’s own runs), grantee (a user currently on the app’s grant list) or other (all remaining callers merged into one group)错误
| HTTP | code | category | 说明 |
|---|---|---|---|
| 401 | unauthorized | forbidden | 缺少或无效的 API Key。 |
| 400 | invalid-group-by | invalid_input | group_by 不在允许的取值内,或组合不合法。 |
| 400 | range-too-wide | invalid_input | 该维度需要同时给出 created_from 与 created_to,且跨度不超过 92 天。 |
| 400 | caller-group-unavailable | invalid_input | group_by=caller 只支持恰好一个私有或分享 App。 |
| 404 | app-not-found | not_found | App 不存在、已改名,或对当前凭证不可见(私有 / 分享范围之外)。 |
{"error": {code, category, message, retryable}},见错误。
