API reference
Usage
Read token and spend rollups for your own org, grouped by end customer, model, or day. Built for agencies that rebill.
Endpoint
Authenticate with the same fw_live_ bearer key you call the model with (see Authentication). The organisation is resolved from the key itself, so the endpoint only ever returns your own usage. There is no parameter that widens the scope.
Query parameters
fromstring (ISO-8601)required2026-07-01T00:00:00Z.tostring (ISO-8601)requiredfrom. The window is half-open, so to is the first instant not counted, which makes consecutive months line up without double-counting the boundary.group_bystringoptionaltenant, model, or day. Defaults to tenant. Anything else returns 400.limitintegeroptional100. Values above 500 are silently clamped to 500 rather than rejected. Must be a positive integer.offsetintegeroptional0. Must be a non-negative integer.from/to returns 400, so pull a long history one quarter at a time.Example
curl -G https://gyld.dev/api/v1/usage \ -H "Authorization: Bearer $GYLD_API_KEY" \ --data-urlencode "from=2026-07-01T00:00:00Z" \ --data-urlencode "to=2026-08-01T00:00:00Z" \ --data-urlencode "group_by=tenant" \ --data-urlencode "limit=100"
The response
{
"rows": [
{
"tenant_ref": "field-office-client-7",
"model": null,
"niche": null,
"day": null,
"prompt_tokens": 41280,
"completion_tokens": 96110,
"total_tokens": 137390,
"amount_micros": 274780
},
{
"tenant_ref": null,
"model": null,
"niche": null,
"day": null,
"prompt_tokens": 900,
"completion_tokens": 2100,
"total_tokens": 3000,
"amount_micros": 6000
}
],
"total": {
"prompt_tokens": 42180,
"completion_tokens": 98210,
"total_tokens": 140390,
"amount_micros": 280780
},
"group_by": "tenant",
"from": "2026-07-01T00:00:00.000Z",
"to": "2026-08-01T00:00:00.000Z",
"limit": 100,
"offset": 0,
"has_more": false
}rowsarrayrequiredgroup_by (see below); the rest are null.totalobjectrequiredgroup_bystringrequiredfromstringrequiredtostringrequiredlimitintegerrequiredoffsetintegerrequiredhas_morebooleanrequiredtrue when more buckets exist past this page.Grouping
Every row carries the same four numeric fields (prompt_tokens, completion_tokens, total_tokens, amount_micros). Only the identity fields change:
| group_by | Populated | Always null |
|---|---|---|
| tenant | tenant_ref | model, niche, day |
| model | model, niche | tenant_ref, day |
| day | day (UTC YYYY-MM-DD) | tenant_ref, model, niche |
nullhere means “not part of this grouping”, with one exception: under group_by=tenant, a null tenant_ref is a real bucket holding every call that arrived without a tenant label.Labelling end customers
tenant_ref comes from an optional X-Gyld-Tenant header on your chat completions calls. Send one label per end customer and the usage endpoint will split their spend out for you.
curl https://gyld.dev/api/v1/chat/completions \
-H "Authorization: Bearer $GYLD_API_KEY" \
-H "X-Gyld-Tenant: field-office-client-7" \
-H "Content-Type: application/json" \
-d '{ "model": "fitness", "messages": [{ "role": "user", "content": "Hi" }] }'- Trimmed, and capped at 64 characters.
- Absent, empty, or whitespace-only is stored as
null. - A value containing control characters is rejected outright and stored as
null, rather than being silently rewritten into a different label.
X-Gyld-Tenant as isolation between your customers.Reading amount_micros
amount_micros is microdollars: one millionth of one US dollar. Divide by 1,000,000 for dollars, so 274780 is $0.27478.
Each row is priced at the rate stored when the call happened, not today’s rate, so a published price change never rewrites the value of past usage. Usage recorded before per-row pricing existed reports amount_micros: 0 while still reporting its real token counts.
amount_micros rather than recomputing from tokens. Recomputing applies the current rate to old usage and will quietly disagree with your invoices.Pagination
Paging is plain offset paging over the grouped buckets: request a page, and if has_more is true, ask again with offset advanced by limit. Keep from, to, and group_by identical across the pages of one report. total is window-wide, so do not sum it across pages.
Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_query | Missing or malformed from/to, to not after from, window over 92 days, unknown group_by, or a non-integer limit/offset. The message names the offending parameter. |
| 401 | invalid_api_key | Missing, malformed, or revoked fw_live_ key. |
Errors use the same envelope as the rest of the API. See Errors & rate limits.