https://app.<BASE_DOMAIN>/api/metrics/v1/. The contract is
docs/reference/openapi/metrics-v1.yaml; the rules around it are section 9 of
docs/reference/control-plane-api.md.
Defaults and limits
Creating a key
An operator creates a key in the console, or withPOST /api/operator/api-keys and a body such as
{"name": "warehouse", "scope": "metrics:read", "expires_in_days": 90}. Add
"tenant_id": "<id>" for a key that reads one tenant. The answer holds the
key (sa_op_ and 40 characters) once; it is never shown again. Only its
SHA-256 and its first 10 characters are stored. Creation is in the audit log
(operator_api_key.create).
Using a key
next_cursor until it is null to read every page. On 429 wait the
Retry-After seconds. The key works only under /api/metrics/v1/; a console
session cookie does not work there.
What each route returns:
/tenants: the tenants the key may read, with site and verification counts./web/daily,/web/dimensions: daily web numbers and breakdowns per tenant from the daily aggregates, the same numbers as the global web view./web/hourly: one tenant’s hourly web numbers read live from Umami, including the current hour./api/daily,/api/routes/daily,/api/hourly: request counts, error rates and p50, p95, p99 per tenant (and per route), the same numbers as the global API view. Data derived from sampled traces is marked withsource: span.
Revoking a key
Revoke in the console or withDELETE /api/operator/api-keys/<id>. The next
request with the key is refused (401); nothing caches a key. Revocation is in
the audit log (operator_api_key.revoke). An expired key is refused the same
way.
Usage
GET /api/operator/api-keys/<id>/usage?from=<day>&to=<day> lists requests
and refusals per hour. Refusals count requests with a revoked or expired key,
over the rate limit, or for a tenant outside the key’s scope. last_used_at
on the key is the last accepted request.