API reference

GET /usage

Read the quota status and daily usage meters for an app.

The usage endpoint reports the authenticated app’s free-quota status for the current UTC day plus a dense day-by-day series you can chart. Use it to show your own dashboard, decide whether to top up credits, or back off before you cross the free allowance. For the conceptual model behind these numbers — the two-band metering, the weighted AI formula, refunds — see Billing.

GET/api/v1/usage

Scope: usage:read Unmetered

This endpoint is deliberately unmetered: reading it never consumes free quota and never debits your wallet. Quota visibility must stay reachable even when you are over quota or out of credits, so it behaves like the models and identity reads — always available to a valid key with the scope.

Scope

The key must carry the usage:read scope (or the * wildcard). A key without it is rejected with 403 insufficient_scope, and the error carries the required scope in its body. See Scopes for the full grant list and Authentication for how a key is resolved to its owner across linked Discord × Google identities.

Query parameters

NameTypeRequiredDescription
days integer No Length of the returned daily series, ending today (UTC). Clamped to the range [1, 90]; the default is 7. A missing, blank, or non-numeric value falls back to 7; an out-of-range value is clamped (below 1 clamps up to 1, above 90 clamps down to 90). The resolved value is echoed back as window_days.

Response fields

On success the endpoint returns 200 with the usual { "data": …, "meta": { "request_id" } } envelope. The data object contains:

FieldTypeDescription
app_idstringThe authenticated app the key belongs to.
datestringToday’s UTC calendar day (YYYY-MM-DD) — the current quota window. Resets at 00:00 UTC.
free_quota_unitsintegerThe app’s free daily allowance in credit units. 0 means unlimited free (the app is never billed).
used_units_todayintegerCredit units consumed by this app so far today (the credit_units meter for date).
remaining_free_unitsinteger | nullFree units left today: max(0, free_quota_units − used_units_today). null when free_quota_units is 0 (unlimited).
billing_enabledbooleanWhether over-quota calls currently debit the owner’s prepaid wallet. When false, over-quota calls stay free but are still metered.
units_per_callintegerThe flat credit cost of one non-AI billable call. 0 means non-AI calls never consume quota or bill.
window_daysintegerThe resolved days value (1–90) — the length of the daily series.
dailyarrayDense day-by-day series, oldest → today, one entry per UTC day (see below). Always window_days entries long.

The daily series

Each element of daily is one UTC calendar day. The series is zero-filled: days with no traffic are still present with zero counters, so a chart never has gaps and you always get exactly window_days ordered points from oldest to newest.

FieldTypeDescription
datestringThe UTC calendar day (YYYY-MM-DD) for this entry.
credit_unitsintegerTotal credit units metered on this day (the quota meter). AI calls contribute weighted token units; flat calls contribute units_per_call.
requestsintegerNumber of billable requests metered on this day, regardless of unit cost.

used_units_today is the live quota-gate counter for the current day and equals the credit_units of the last (today’s) entry in daily. Both come from the same durable daily counter, so they are always consistent within one response.

Request

cURL
curl "https://exe.krallo.com/api/v1/usage?days=7" \
  -H "Authorization: Bearer krallo_live_..."
Node.js
const res = await fetch("https://exe.krallo.com/api/v1/usage?days=7", {
  headers: { Authorization: `Bearer ${process.env.KRALLO_API_KEY}` },
});
const { data } = await res.json();
console.log(
  `Used ${data.used_units_today} of ` +
    (data.free_quota_units === 0
      ? "unlimited"
      : `${data.free_quota_units}`) +
    ` free units today.`,
);

Response

A metered day and several quiet ones, with the free quota still in effect and billing off:

{
  "data": {
    "app_id": "01J8ZBQ2C4D6E8F0G2H4J6K8M0",
    "date": "2026-07-15",
    "free_quota_units": 10000,
    "used_units_today": 148,
    "remaining_free_units": 9852,
    "billing_enabled": false,
    "units_per_call": 1,
    "window_days": 7,
    "daily": [
      { "date": "2026-07-09", "credit_units": 0,    "requests": 0  },
      { "date": "2026-07-10", "credit_units": 512,  "requests": 34 },
      { "date": "2026-07-11", "credit_units": 96,   "requests": 12 },
      { "date": "2026-07-12", "credit_units": 0,    "requests": 0  },
      { "date": "2026-07-13", "credit_units": 1240, "requests": 71 },
      { "date": "2026-07-14", "credit_units": 380,  "requests": 22 },
      { "date": "2026-07-15", "credit_units": 148,  "requests": 9  }
    ]
  },
  "meta": { "request_id": "c2a4e6d8-1b3f-4a5c-9e7d-0f2b4c6d8e1a" }
}

When the app’s allowance is set to unlimited (free_quota_units of 0), remaining_free_units is null rather than a number:

{
  "data": {
    "app_id": "01J8ZBQ2C4D6E8F0G2H4J6K8M0",
    "date": "2026-07-15",
    "free_quota_units": 0,
    "used_units_today": 148,
    "remaining_free_units": null,
    "billing_enabled": true,
    "units_per_call": 1,
    "window_days": 7,
    "daily": [ /* ... */ ]
  },
  "meta": { "request_id": "d5b7a9c1-3e2f-4d6b-8c0a-1f3e5d7b9a2c" }
}

Errors

Errors use the standard error envelope ({ "error": { "code", "message", … }, "meta": { "request_id" } }). Because the endpoint is unmetered, it never returns 402 insufficient_credits.

StatusCodeWhen
401unauthorizedNo bearer token was sent.
401invalid_tokenThe bearer token is malformed or unknown.
401token_revoked / token_expiredThe key was revoked or has passed its expiry. See Authentication.
403insufficient_scopeThe key lacks usage:read. The error body includes required_scope. See Scopes.
403app_disabledThe owning app is disabled.
403owner_suspendedThe account behind the key is suspended.
404not_foundThe Developer API is turned off platform-wide, or the app could not be resolved for this owner.
405method_not_allowedAny method other than GET.
429rate_limitedThe per-key rate limit was exceeded. See Rate limits.
500internal_errorThe usage counter store was unavailable. The endpoint fails closed rather than reporting a wrong number.

Related