Documentation Index
Fetch the complete documentation index at: https://docs.textql.com/llms.txt
Use this file to discover all available pages before exploring further.
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://app.textql.com/v1/billing
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://app.textql.com/v1/billing/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://app.textql.com/v1/billing/usage?start_date=2026-01-01T00:00:00Z&end_date=2026-02-01T00: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://app.textql.com/v1/billing/usage?granularity=month' \
-H 'Authorization: Bearer YOUR_TOKEN'
Filtering
By organization — useful for tenants with multiple orgs:
curl 'https://app.textql.com/v1/billing/usage?organization=acme-engineering,acme-research' \
-H 'Authorization: Bearer YOUR_TOKEN'
By user email — case-insensitive:
curl 'https://app.textql.com/v1/billing/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://app.textql.com/v1/billing/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://app.textql.com/v1/billing/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://app.textql.com/v1/billing/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://app.textql.com/v1/billing/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://app.textql.com/v1/billing"
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://app.textql.com/v1/billing";
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.