Ingests a batch of account-usage samples — what a developer's OWN AI accounts…
Ingests a batch of account-usage samples — what a developer's OWN AI accounts have consumed of their OWN plans, metered from each provider's own login —…
POST /v1/usage
| Address | https://api.hanzo.ai/v1/usage |
| Method | POST |
| Operation | post_usage |
| Auth | Authorization: Bearer $HANZO_API_KEY |
Ingests a batch of account-usage samples — what a developer's OWN AI accounts have consumed of their OWN plans, metered from each provider's own login — and appends them to the warehouse series. Answers 202.
Send either a samples array or one sample's fields at the top level. Every
sample needs a provider, a machine and a known window class; an unknown window or
kind is refused rather than silently rewritten, because a dash filled with a class
nobody reported is worse than an error. There is no timestamp field: the server
owns the observation clock, and a sample says which window it measured with
windowStart or resetsAt.
It is FAIL-SOFT on storage: a warehouse outage costs a poll of history (stored:false), never a failed request. It records usage ONLY — the link registry is refreshed separately via POST /v1/link, so there is one and only one way to update an account row.
Request
43 fields, body application/json (required).
| Field | In | Type | Required | Description |
|---|---|---|---|---|
account | body | string | — | Account is the linked account the window was metered from. |
cachedInputTokens | body | integer | — | CachedInputTokens is the prompt tokens the provider served from cache. |
confidence | body | string | — | Confidence says how much the counters below mean. |
costCents | body | integer | — | CostCents is what the window cost on the PROVIDER's own plan, in US cents. |
costLimitCents | body | integer | — | CostLimitCents is the plan's spend ceiling for the window, in US cents. |
currency | body | string | — | Currency is the provider's currency when it is not US cents. |
inputTokens | body | integer | — | InputTokens is prompt tokens consumed in the window. |
kind | body | string | — | Kind is subscription or apikey. |
lane | body | string | — | Lane is the meter lane within the account. |
machine | body | string | — | Machine is the host whose meter read the window. |
outputTokens | body | integer | — | OutputTokens is completion tokens produced in the window. |
plan | body | string | — | Plan is the subscription plan the account is on, as the provider names it. |
provider | body | string | — | Provider is the upstream the account belongs to, e.g. |
requests | body | integer | — | Requests is how many requests the window covers. |
resetsAt | body | string | — | ResetsAt is when the measured window rolls over, RFC3339. |
samples | body | sampleReq[] | — | Samples is the batch form: every lane a poller measured, in one call. |
samples[].account | body | string | — | Account is the linked account the window was metered from. |
samples[].cachedInputTokens | body | integer | — | CachedInputTokens is the prompt tokens the provider served from cache. |
samples[].confidence | body | string | — | Confidence says how much the counters below mean. |
samples[].costCents | body | integer | — | CostCents is what the window cost on the PROVIDER's own plan, in US cents. |
samples[].costLimitCents | body | integer | — | CostLimitCents is the plan's spend ceiling for the window, in US cents. |
samples[].currency | body | string | — | Currency is the provider's currency when it is not US cents. |
samples[].inputTokens | body | integer | — | InputTokens is prompt tokens consumed in the window. |
samples[].kind | body | string | — | Kind is subscription or apikey. |
samples[].lane | body | string | — | Lane is the meter lane within the account. |
samples[].machine | body | string | — | Machine is the host whose meter read the window. |
samples[].outputTokens | body | integer | — | OutputTokens is completion tokens produced in the window. |
samples[].plan | body | string | — | Plan is the subscription plan the account is on, as the provider names it. |
samples[].provider | body | string | — | Provider is the upstream the account belongs to, e.g. |
samples[].requests | body | integer | — | Requests is how many requests the window covers. |
samples[].resetsAt | body | string | — | ResetsAt is when the measured window rolls over, RFC3339. |
samples[].synthetic | body | boolean | — | Synthetic marks a window the meter inferred rather than read. |
samples[].totalTokens | body | integer | — | TotalTokens is the window's total tokens. |
samples[].usedPct | body | number | — | UsedPct is how much of the window's allowance is consumed, 0–100. |
samples[].window | body | string | — | Window is the window class: 6h, day, week or month. |
samples[].windowMinutes | body | integer | — | WindowMinutes is the window's real length in minutes, as the meter reports it. |
samples[].windowStart | body | string | — | WindowStart is when the measured window opened, RFC3339. |
synthetic | body | boolean | — | Synthetic marks a window the meter inferred rather than read. |
totalTokens | body | integer | — | TotalTokens is the window's total tokens. |
usedPct | body | number | — | UsedPct is how much of the window's allowance is consumed, 0–100. |
window | body | string | — | Window is the window class: 6h, day, week or month. |
windowMinutes | body | integer | — | WindowMinutes is the window's real length in minutes, as the meter reports it. |
windowStart | body | string | — | WindowStart is when the measured window opened, RFC3339. |
Response
| Status | Body | Meaning |
|---|---|---|
202 | reportResp | accepted |
202 body — 2 fields.
| Field | In | Type | Always | Description |
|---|---|---|---|---|
accepted | body | integer | — | Accepted is how many samples passed validation. |
stored | body | boolean | — | Stored is whether the warehouse actually persisted them. |
Failure carries the platform error shape — see Errors.
Examples
hanzo usage createimport { Configuration, UsageApi } from 'hanzoai';
const api = new UsageApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postUsage({ account: "<account>", cachedInputTokens: 0 });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).post_usage(account="<account>", cached_input_tokens=0)cfg := cloud.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := cloud.NewAPIClient(cfg)
resp, _, err := client.UsageAPI.PostUsage(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::post_usage(&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).postUsage();curl -X POST https://api.hanzo.ai/v1/usage \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"account": "<account>",
"cachedInputTokens": 0
}'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?