Hanzo

Analytics

Package analytics is product analytics: send an event, read back who did what.

Package analytics is product analytics: send an event, read back who did what.

Base URLhttps://api.hanzo.ai
Operations4
AuthAuthorization: Bearer $HANZO_API_KEY

analytics

GET /v1/analytics/health

Health reports whether the event plane can take a write and the warehouse can answer a read.

It reports the analytics subsystem's own liveness in BOTH directions: plane is the event plane it WRITES (the bus and the JetStream stream every accepted event is published to, both named in the report), and datastore is the warehouse it READS, with each read lens's table reported as it is provisioned (the LLM usage ledger and the product-event table).

EITHER ONE DOWN IS A 503, and the report says WHICH — they are probed independently and never collapse into a single bit. This endpoint used to report the read half only, and answered 200/ok while every POST /v1/event failed on a stream that could not bind: a total ingest outage behind a green probe. A readiness gate here now gates on the write path too.

plane.ready IS A REAL PROBE and walks the ingest path itself — the same connection and the same stream a publish uses — so it cannot answer ready while a publish would 503. plane.reason carries the plane's own error text when it is false.

datastore IS NOT PROBED WITH A QUERY. It is the state of the process's own shared client — established, and not since closed — so a warehouse accepting connections and failing reads still reports true. Degraded CARRIES the report (status, the failing half, reason) as its body rather than an error envelope, so a gate reads the cause off the same object it got at 200.

A MISSING LENS TABLE IS NOT A FAILURE and never moves the status: a lens reported available:false answers honest-empty rather than erroring, so a fresh deployment whose collector has not emitted yet is legitimately 200 with the product-event lens unavailable. The lens block is reported whenever the warehouse is REACHABLE — including on a report degraded by the plane, where the tables genuinely were probed — and is absent only when the warehouse is not, having nothing to say about tables it could not reach.

Unauthenticated on purpose — liveness has to be probe-able — and it reads NO tenant data: table existence and stream presence only, never a row and never an event.

GET /v1/analytics/overview

Overview returns the caller org's analytics KPIs for one time window. Three lenses over one warehouse: llm is the live per-org LLM usage ledger (requests, tokens, spend, models, providers, errors) and is always real; web (pageviews, visitors, sessions) and commerce (orders, revenue, AOV) read the product-event table and report available=false rather than fabricating zeros when it holds nothing yet.

The org is the validated principal's — never a parameter — so a caller can only ever read its own tenant. 403 without a validated bearer, 400 on an unknown range, 503 when the warehouse is unreachable.

ParameterInTypeRequiredDescription
rangequerystringRange is a relative window: 24h, 7d or 30d. Default 24h. Ignored when both start and end are given.
startquerystringStart is the inclusive lower bound of a custom window, RFC3339.
endquerystringEnd is the exclusive upper bound of a custom window, RFC3339.

GET /v1/analytics/timeseries

Timeseries returns the caller org's LLM usage over time as an evenly-spaced series. One point per hour or per day — the bucket the window implies, 24h giving hours and 7d/30d giving days — carrying requests, total tokens and spend in cents. Empty buckets are filled with zeros so a client charts a continuous line.

The org is the validated principal's — never a parameter. 403 without a validated bearer, 400 on an unknown range, 503 when the warehouse is unreachable.

ParameterInTypeRequiredDescription
rangequerystringRange is a relative window: 24h, 7d or 30d. Default 24h. Ignored when both start and end are given.
startquerystringStart is the inclusive lower bound of a custom window, RFC3339.
endquerystringEnd is the exclusive upper bound of a custom window, RFC3339.

GET /v1/analytics/top

Top returns the caller org's ranked lenses for one window, five of them at once. models ranks LLM models by spend and is always real; products ranks commerce orders by revenue; topPages ranks requested paths, topReferrers the external referrer domains ("(direct)" for a missing or same-origin one) and topSources the utm_source campaigns ("(none)" when absent), each by pageviews. Every lens carries each row's share of the in-window total, so a top-N honestly shows the long tail.

The four event lenses report available=false rather than fabricating zeros when the product-event table holds nothing yet. The org is the validated principal's — never a parameter. 403 without a validated bearer, 400 on an unknown range, 503 when the warehouse is unreachable.

ParameterInTypeRequiredDescription
rangequerystringRange is a relative window: 24h, 7d or 30d. Default 24h. Ignored when both start and end are given.
startquerystringStart is the inclusive lower bound of a custom window, RFC3339.
endquerystringEnd is the exclusive upper bound of a custom window, RFC3339.
limitqueryintegerLimit bounds every ranked lens in the response.

Analytics guide · All Hanzo APIs · Interactive reference

How is this guide?

On this page