Publisher usage analytics (all my apps, filterable)
How my apps are being called over a period: range totals plus a
breakdown by day (or by hour for short ranges), by app or by calling
channel (or two of these crossed), or — for diagnosis — by final
state, by app version or by error code. The publisher-side
counterpart of GET /billing — same vocabulary (created_from /
created_to are ISO-8601 absolute timestamps, inclusive start /
exclusive end, attributed by run start time; tz_offset only moves
day boundaries; data_app / triggered_by narrow the set),
ownership flips from “runs I started” to “apps I own” (zero-Release
apps included).
Day / hour / app / channel breakdowns come from hourly pre-aggregated
buckets (accumulated at terminal states), so any range and any
whole-hour offset is exact and cheap. State / version / error
breakdowns are computed from run details on demand and therefore
require both bounds at most 92 days apart (400 range-too-wide);
error groups only cover runs that carry an error and each one brings
the most recent error message as sample_message. Debug traffic
(run_kind=test) is excluded by default; platform health probes never
count. Success counts partial successes; cancellations leave the
success-rate denominator; metrics with no finished run are null
rather than 0. amount is what callers paid for these runs (data
fees), not the publisher’s earnings.
Day / hour groups are ascending (hour keys are local wall-clock
YYYY-MM-DDTHH:00 under tz_offset, no zone suffix), other groups by
run count descending. Unknown or other people’s apps in data_app
are 404 (no existence leak). group_by outside the vocabulary, or
combining day with hour, is 400 invalid-group-by.
Callers: totals.callers (and previous_totals.callers) is the
number of distinct users who called in the range — it comes from run
details, so it is null unless the range is bounded and at most 92
days. group_by=caller breaks a single private or shared app
down by caller: the publisher’s own runs (caller_kind=owner) and
users currently on the grant list (grantee) are named by their
current username; everyone else (former grantees, callers from a
public period) is merged into one other group. It is 400
caller-group-unavailable for a public app or for more than one app
— a public app’s callers are anonymous and only counted.
Authorizations
DataHub API Key
Query Parameters
one or two comma-separated dimensions from day / hour / data_app / triggered_by / state / version / error / caller (e.g. day,data_app); day and hour are two granularities of the same time axis and cannot be combined; state / version / error / caller are computed from run details and need a bounded range of at most 92 days; caller additionally needs exactly one private or shared data_app; default day
restrict to these apps (<username>/<app_name>, repeatable); default = all my apps
timezone offset for day / hour buckets (minutes relative to UTC, e.g. 480 for UTC+8); default 0 means UTC. Fixed offset, no DST; buckets are hourly so half-hour offsets are approximated to the hour
-720 <= x <= 840restrict to one calling channel (api / sdk / mcp / web …, the same value as the runs list filter)
also return previous_totals for the equal-length range immediately before created_from (requires both bounds)
Response
Successful Response
Publisher-side usage analytics: totals over the range (optionally the preceding equal-length range for period-over-period comparison) and a breakdown by up to two dimensions.