import requests
url = "https://app.langwatch.ai/api/gateway/v1/spend-summaries"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.langwatch.ai/api/gateway/v1/spend-summaries', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));curl --request GET \
--url https://app.langwatch.ai/api/gateway/v1/spend-summaries \
--header 'Authorization: Bearer <token>'{
"data": [
{
"key": "<string>",
"group": {},
"bucket_start": "<string>",
"event_count": 123,
"settled_count": 123,
"usage": {
"input_tokens": 123,
"output_tokens": 123,
"cache_read_input_tokens": 123,
"cache_creation_input_tokens": 123,
"reasoning_tokens": 123
},
"cost": {
"total_usd": "<string>",
"nano_usd": 123
}
}
],
"next_cursor": "<string>"
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"meta": {},
"trace_id": "<string>",
"span_id": "<string>"
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"meta": {},
"trace_id": "<string>",
"span_id": "<string>"
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"meta": {},
"trace_id": "<string>",
"span_id": "<string>"
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"meta": {},
"trace_id": "<string>",
"span_id": "<string>"
}
}List spend summaries
Reconciliation checksum fast path: spend rollups with token classes and integer nano-USD cost. Settled (unpriced) requests are counted separately as settled_count and never included in cost sums. Diff individual items via /spend-events only when a checksum diverges. group_by takes one or two of virtual_key, end_user, project, model, provider, principal and request_type, comma-separated, and bucket adds an hour or day column in the timezone you name. key stays the first dimension’s value for consumers written against the single-dimension surface; read group to tell two dimensions apart. Paged by group key ascending: follow next_cursor until it comes back null, because a page that is full does not mean the window held nothing more. Grouping by model or provider, or into time buckets, is refused with gateway_spend_group_by_unstable while the window is recent enough that outcomes can still arrive, because those groups can move under a page walk and the totals would double-count some requests and miss others; ask for an older range, or send allow_unstable when an approximate shape is enough. Every filter here is accepted by /spend-events too, and the reverse holds apart from status=admitted: a rollup sums the cost of requests past admission, so an admitted request has none to contribute and that narrowing is refused rather than answered with a zero. Ask /spend-events for those.
import requests
url = "https://app.langwatch.ai/api/gateway/v1/spend-summaries"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.langwatch.ai/api/gateway/v1/spend-summaries', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));curl --request GET \
--url https://app.langwatch.ai/api/gateway/v1/spend-summaries \
--header 'Authorization: Bearer <token>'{
"data": [
{
"key": "<string>",
"group": {},
"bucket_start": "<string>",
"event_count": 123,
"settled_count": 123,
"usage": {
"input_tokens": 123,
"output_tokens": 123,
"cache_read_input_tokens": 123,
"cache_creation_input_tokens": 123,
"reasoning_tokens": 123
},
"cost": {
"total_usd": "<string>",
"nano_usd": 123
}
}
],
"next_cursor": "<string>"
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"meta": {},
"trace_id": "<string>",
"span_id": "<string>"
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"meta": {},
"trace_id": "<string>",
"span_id": "<string>"
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"meta": {},
"trace_id": "<string>",
"span_id": "<string>"
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"meta": {},
"trace_id": "<string>",
"span_id": "<string>"
}
}Authorizations
Admin API key for organization-level operations (managing projects, API keys). Create one in Settings > API Keys or via POST /api/api-keys. Format: sk-lw-{id}_{secret}.
Query Parameters
One or two dimensions, comma separated: virtual_key, end_user, project, model, provider, principal, request_type. A dimension may not repeat. Each row's key is the first dimension's value and group names them all, so two rows may share a key.
"model,end_user"
none, hour, day 1 - 64true, 1, yes for yes; false, 0, no or omitted for no. Case does not matter, so a Python True is accepted as sent.
"true"
Milliseconds since the Unix epoch, not seconds. An epoch in seconds is a valid integer here and answers for 1970, so a mismatched unit reads as an empty window rather than as an error.
x <= 90071992547409911782864000000
Milliseconds since the Unix epoch, not seconds. An epoch in seconds is a valid integer here and answers for 1970, so a mismatched unit reads as an empty window rather than as an error.
x <= 90071992547409911782864000000
500x <= 10001 - 1001 - 1001 - 2001 - 1001 - 2561 - 1001 - 2001 - 1001 - 501 - 2003 - 640Narrow to one lifecycle status. admitted is not accepted here: a rollup sums the cost of requests past admission, and an admitted request is still in flight with no cost of its own yet. Ask /spend-events for those.
success, error, confirmed, failed, settled Was this page helpful?