List analytics

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.

GET /v1/usage/analytics

Addresshttps://api.hanzo.ai/v1/usage/analytics
MethodGET
Operationget_usage_analytics
AuthAuthorization: Bearer $HANZO_API_KEY

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.

FieldInTypeRequiredDescription
endquerystring—End is the exclusive window end, RFC3339.
planquerystring—Plan is the plan id whose entitlement decides access and retention.
rangequerystring—Range is the window: a count and a unit — 24h, 7d, 90d, any <N>h or <N>d — or day, week, month, all, custom.
startquerystring—Start is the inclusive window start, RFC3339.

Response

StatusBodyMeaning
200usage.usageAnalyticsViewok
defaultproblem-detailsrefused

200 body — 17 fields.

FieldInTypeAlwaysDescription
endbodystring—End is the window's exclusive end, RFC3339 UTC.
exportbodyboolean—Export is whether the resolved plan allows exporting these rows.
planbodystring—Plan echoes the plan id the entitlement was resolved from.
providersbodyusage.ProviderBreakdown—
providers.availablebodyboolean—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.itemsbodyusage.ProviderRow[]—Items is one row per provider, most tokens first.
providers.items[].costCentsbodyinteger (int64)—CostCents is what they cost the org, in US cents.
providers.items[].providerbodystring—Provider is the upstream the requests were routed to, e.g. anthropic.
providers.items[].requestsbodyinteger (int64)—Requests is how many completions the org made against that provider.
providers.items[].tokensbodyinteger (int64)—Tokens is the total tokens those completions consumed, prompt plus completion.
providers.sourcebodystring—Source names the warehouse table the rows came from.
rangebodystring—Range is the label that was ASKED for.
retentionDaysbodyinteger (int64)—RetentionDays is how far back the resolved plan allows reading.
scopebodyusage.usageScope—
scope.orgbodystring—Org is the IAM org slug the rows were read under — the validated principal's, never a client header.
scope.userbodystring—User is the caller's own subject, whose linked-account rows the accounts block carries.
startbodystring—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 get
import { 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 := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.UsageAPI.GetUsageAnalytics(context.Background()).Execute()
if err != nil {
	return err
}
use hanzo_client::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.setBearerToken(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"

MCP reaches usage through the usage tool, which names its 5 operations with its own verbs — this one among them, under a name only MCP 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"
         }
       }
     }'

Usage API · All Hanzo APIs · Interactive reference

Was this page useful?