Overview
The Usage API lets you pull ACU (Activity Consumption Unit) consumption data for your organization programmatically — by time period, user, or usage category. Use it to build internal dashboards, feed billing systems, or monitor spend across teams.
Base URL: https://api.console.textql.com/billing/v1
You can query usage data directly in Ana without any API setup. The TextQL Usage connector is already available in your platform inside the connector selection.
Authentication
All requests require a Bearer token. Your token is a Base64-encoded string in the format {member_id}:{api_token}, created in Settings → Developers → API Keys.
Pass it in one of two ways:
# Authorization header
-H 'Authorization: Bearer YOUR_TOKEN'
# Or as a custom header
-H 'tql_api_key: YOUR_TOKEN'
Your First Request
Fetch the last 90 days of usage for your organization with a single call:
curl 'https://api.console.textql.com/billing/v1/usage' \
-H 'Authorization: Bearer YOUR_TOKEN'
Response:
{
"data": [
{
"start_datetime": "2026-01-31T00:00:00Z",
"end_datetime": "2026-02-01T00:00:00Z",
"organization": "acme-engineering",
"email": "m.chen@acme.com",
"category": "llm_tokens",
"acu": 8241.05
}
],
"pagination": {
"page": 1,
"page_size": 100,
"total_count": 3
}
}
Each record represents one user’s usage within one time bucket, for one category.
Parameters
All parameters are optional query parameters on GET /usage.
Date Range
| Parameter | Format | Default | Description |
|---|
start_date | RFC 3339 | 90 days before end_date | Inclusive lower bound |
end_date | RFC 3339 | Current UTC time | Exclusive upper bound |
# Usage for January 2026
curl 'https://api.console.textql.com/billing/v1/usage?start_date=2026-01-01T00:00:00Z&end_date=2026-01-31T23:00:00Z' \
-H 'Authorization: Bearer YOUR_TOKEN'
Granularity
Controls the size of each time bucket. Defaults to day.
| Value | Bucket size |
|---|
hour | 1 hour |
day | 1 calendar day |
month | 1 calendar month |
# Monthly rollup
curl 'https://api.console.textql.com/billing/v1/usage?granularity=month' \
-H 'Authorization: Bearer YOUR_TOKEN'
Filtering
By organization — useful for tenants with multiple orgs:
curl 'https://api.console.textql.com/billing/v1/usage?organization=acme-engineering,acme-research' \
-H 'Authorization: Bearer YOUR_TOKEN'
By user email — case-insensitive:
curl 'https://api.console.textql.com/billing/v1/usage?email=j.ramirez@acme.com,s.patel@acme.com' \
-H 'Authorization: Bearer YOUR_TOKEN'
By usage category:
| Category | What it measures |
|---|
llm_tokens | LLM inference consumption |
compute_hours | Python and execution environment usage |
cell_executions | Individual cell runs |
curl 'https://api.console.textql.com/billing/v1/usage?category=llm_tokens,compute_hours' \
-H 'Authorization: Bearer YOUR_TOKEN'
Filters can be combined freely:
# LLM usage for one user, by hour, for a specific week
curl 'https://api.console.textql.com/billing/v1/usage?email=m.chen@acme.com&category=llm_tokens&granularity=hour&start_date=2026-01-27T00:00:00Z&end_date=2026-02-03T00:00:00Z' \
-H 'Authorization: Bearer YOUR_TOKEN'
Sorting
Use the sort parameter to control result order. Prefix with - for descending.
| Value | Description |
|---|
start_datetime | Oldest first |
-start_datetime | Newest first (default) |
acu | Lowest usage first |
-acu | Highest usage first |
email | Alphabetical by user |
-email | Reverse alphabetical by user |
curl 'https://api.console.textql.com/billing/v1/usage?sort=-acu' \
-H 'Authorization: Bearer YOUR_TOKEN'
| Parameter | Default | Max |
|---|
page_size | 100 | 1000 |
page | 1 | — |
# Page 2, 50 records per page
curl 'https://api.console.textql.com/billing/v1/usage?page=2&page_size=50' \
-H 'Authorization: Bearer YOUR_TOKEN'
Use pagination.total_count in the response to calculate how many pages exist.
Code Examples
Python — fetch all records across pages:
import requests
TOKEN = "your-token"
BASE = "https://api.console.textql.com/billing/v1"
headers = {"Authorization": f"Bearer {TOKEN}"}
def get_all_usage(**params):
records = []
page = 1
while True:
resp = requests.get(f"{BASE}/usage", headers=headers, params={**params, "page": page, "page_size": 1000})
data = resp.json()
records.extend(data["data"])
if len(records) >= data["pagination"]["total_count"]:
break
page += 1
return records
# Example: all LLM usage for January, grouped by month
usage = get_all_usage(
start_date="2026-01-01T00:00:00Z",
end_date="2026-02-01T00:00:00Z",
granularity="month",
category="llm_tokens",
)
JavaScript:
const TOKEN = "your-token";
const BASE = "https://api.console.textql.com/billing/v1";
async function getUsage(params = {}) {
const query = new URLSearchParams(params).toString();
const res = await fetch(`${BASE}/usage?${query}`, {
headers: { Authorization: `Bearer ${TOKEN}` },
});
return res.json();
}
// Example: top spenders this month
const data = await getUsage({
granularity: "month",
sort: "-acu",
page_size: 10,
});
Response Fields
| Field | Type | Description |
|---|
start_datetime | string (UTC) | Start of the time bucket, inclusive |
end_datetime | string (UTC) | End of the time bucket, exclusive |
organization | string | Organization name |
email | string | User email (lowercase). Empty if usage cannot be attributed to a specific user |
category | string | Usage category |
acu | number | Usage in ACUs. Records with zero or negative values are omitted |
Error Reference
| Status | Code | Cause |
|---|
| 400 | invalid_parameter | Bad date range, unknown category, unknown org, or invalid granularity |
| 401 | unauthorized | Token is missing, invalid, or expired |
| 403 | forbidden | Token does not have access to the requested organization’s data |
Troubleshooting & Support
| Problem | What to check |
|---|
| 401 on every request | Confirm your token is Base64-encoded in {member_id}:{api_token} format and hasn’t expired |
| 403 on a specific org | Your API key may not have access to that organization — check your role in Settings → Members |
Empty data array | The filters you applied may return no records — try widening the date range or removing category/email filters |
acu values seem low | Records with zero or negative ACU are omitted; usage may also be split across multiple category buckets |
| Unknown org error | The organization value must match the org name exactly as it appears in TextQL |
If you’re still running into issues, contact support at support@textql.com and include the full request URL and response body.