Is the entitlement-GATED per-provider breakdown of the caller org's LLM usage —…
Is the entitlement-GATED per-provider breakdown of the caller org's LLM usage — the paid lens over the same warehouse ledger GET /v1/usage/summary reads…
GET /v1/usage/analytics
| Address | https://api.hanzo.ai/v1/usage/analytics |
| Method | GET |
| Operation | get_usage_analytics |
| Auth | Authorization: Bearer $HANZO_API_KEY |
Is the entitlement-GATED per-provider breakdown of the caller org's LLM usage — the paid lens over the same warehouse ledger GET /v1/usage/summary reads its totals from. Basic own-org usage stays ungated at /v1/usage/summary.
A plan that does not grant the analytics datastore is refused with 402, and an unresolvable plan fails closed to the free floor, which does not grant it. The window is clamped forward to the plan's retention entitlement, so a tenant can never read older than its plan allows even with a custom start. The response is marked no-store.
INTERIM (mirrors apps/world's limits echo): no org→plan resolver exists in cloud yet — the subscription lookup is owned by the billing plane and the gateway principal carries no plan claim — so the caller passes the plan and the gate resolves THAT plan's access.
Request
4 fields.
| Field | In | Type | Required | Description |
|---|---|---|---|---|
end | query | string | — | End is the exclusive window end, RFC3339. |
plan | query | string | — | Plan is the plan id whose entitlement decides access and retention. |
range | query | string | — | Range is the window: a count and a unit — 24h, 7d, 90d, any <N>h or <N>d — or day, week, month, all, custom. Empty means 24h. |
start | query | string | — | Start is the inclusive window start, RFC3339. |
Response
| Status | Body | Meaning |
|---|---|---|
200 | usageAnalyticsView | ok |
200 body — 17 fields.
| Field | In | Type | Always | Description |
|---|---|---|---|---|
end | body | string | — | End is the window's exclusive end, RFC3339 UTC. |
export | body | boolean | — | Export is whether the resolved plan allows exporting these rows. |
plan | body | string | — | Plan echoes the plan id the entitlement was resolved from. |
providers | body | ProviderBreakdown | — | |
providers.available | body | boolean | — | Available is false when the warehouse could not be read, which means "no answer" and NOT "no usage" — Items is then empty for a reason. |
providers.items | body | ProviderRow[] | — | Items is one row per provider, most tokens first. |
providers.items[].costCents | body | integer | — | CostCents is what they cost the org, in US cents. |
providers.items[].provider | body | string | — | Provider is the upstream the requests were routed to, e.g. |
providers.items[].requests | body | integer | — | Requests is how many completions the org made against that provider. |
providers.items[].tokens | body | integer | — | Tokens is the total tokens those completions consumed, prompt plus completion. |
providers.source | body | string | — | Source names the warehouse table the rows came from. |
range | body | string | — | Range is the label that was ASKED for. A plan whose retention is shorter than that window is served the retention instead, so read start and end for the window… |
retentionDays | body | integer | — | RetentionDays is how far back the resolved plan allows reading. |
scope | body | usageScope | — | |
scope.org | body | string | — | Org is the IAM org slug the rows were read under — the validated principal's, never a client header. |
scope.user | body | string | — | User is the caller's own subject, whose linked-account rows the accounts block carries. |
start | body | string | — | Start is the window's inclusive start, RFC3339 UTC, AFTER the retention clamp — so it may be later than the start that was asked for. |
Failure carries the platform error shape — see Errors.
Examples
hanzo usage analytics getimport { Configuration, UsageApi } from 'hanzoai';
const api = new UsageApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.getUsageAnalytics();from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import UsageApi
client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = UsageApi(client).get_usage_analytics()cfg := cloud.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := cloud.NewAPIClient(cfg)
resp, _, err := client.UsageAPI.GetUsageAnalytics(context.Background()).Execute()
if err != nil {
return err
}use hanzo_cloud::apis::{configuration::Configuration, usage_api};
let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();
let result = usage_api::get_usage_analytics(&cfg, Default::default()).await?;import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.UsageApi;
ApiClient client = new ApiClient();
client.setRequestInterceptor(b -> b.header("Authorization", "Bearer " + System.getenv("HANZO_API_KEY")));
var result = new UsageApi(client).getUsageAnalytics();curl https://api.hanzo.ai/v1/usage/analytics \
-H "Authorization: Bearer $HANZO_API_KEY"The door reaches usage through the usage tool, which names its 5 operations with its own verbs — this one among them, under a name only the door declares. describe explains any of them:
curl -X POST https://api.hanzo.ai/v1/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "describe",
"arguments": {
"op": "list_usage_analytics"
}
}
}'How is this guide?