Advanced Consumption Reports
On this page
Building consumption reports
Consumption data that no one looks at is useless. A report is only useful if it answers a question you actually ask, and there are only three: is it increasing, did something abnormal happen, and where is the money going.
The next three sections address these questions in that order. Each produces a number you can act on—not just another chart.
Comparative monthly report
Consumption only makes sense in comparison. $400 in a month is neither good nor bad in absolute terms: what matters is whether it follows a $200 month or a $600 month. Always contextualize changes with what you know about activity—a 40% increase after launching a feature is expected, the same increase with nothing new warrants opening the next section.
import requests
import json
MANAGEMENT_API = "https://management-api.x.ai"
MGMT_KEY = "xai-mgmt-..."
TEAM_ID = "team-..."
def get_monthly_usage(year, month):
"""Retrieves total consumption for a given month."""
next_month = month + 1 if month < 12 else 1
next_year = year if month < 12 else year + 1
response = requests.post(
f"{MANAGEMENT_API}/v1/billing/teams/{TEAM_ID}/usage",
headers={
"Authorization": f"Bearer {MGMT_KEY}",
"Content-Type": "application/json"
},
json={
"analyticsRequest": {
"timeRange": {
"startTime": f"{year}-{month:02d}-01 00:00:00",
"endTime": f"{next_year}-{next_month:02d}-01 00:00:00",
"timezone": "Europe/Paris"
},
"timeUnit": "MONTH",
"values": [
{"name": "tokens", "aggregation": "SUM"},
{"name": "requests", "aggregation": "COUNT"}
],
"groupBy": ["model"]
}
}
)
return response.json()
# Compare March and April 2026
march = get_monthly_usage(2026, 3)
april = get_monthly_usage(2026, 4)
print("=== Comparative Report March vs April 2026 ===")
print(json.dumps(march, indent=2))
print(json.dumps(april, indent=2))
Anomaly detection
Standard deviation defines “abnormal” here without needing to set an arbitrary threshold: a day beyond two standard deviations from your average falls outside the usual pattern, regardless of your volume. This is the method that adapts automatically as your activity grows, where a dollar threshold becomes obsolete the following month.
import requests
import statistics
MANAGEMENT_API = "https://management-api.x.ai"
MGMT_KEY = "xai-mgmt-..."
TEAM_ID = "team-..."
# Retrieve daily consumption for the month
response = requests.post(
f"{MANAGEMENT_API}/v1/billing/teams/{TEAM_ID}/usage",
headers={
"Authorization": f"Bearer {MGMT_KEY}",
"Content-Type": "application/json"
},
json={
"analyticsRequest": {
"timeRange": {
"startTime": "2026-03-01 00:00:00",
"endTime": "2026-04-01 00:00:00",
"timezone": "Europe/Paris"
},
"timeUnit": "DAY",
"values": [{"name": "tokens", "aggregation": "SUM"}]
}
}
)
data = response.json()
daily_values = [point.get("value", 0) for point in data.get("dataPoints", [])]
if daily_values:
mean = statistics.mean(daily_values)
stdev = statistics.stdev(daily_values) if len(daily_values) > 1 else 0
threshold = mean + 2 * stdev # Threshold at 2 standard deviations
for i, val in enumerate(daily_values):
if val > threshold:
print(f"Day {i+1}: {val} tokens (anomaly, threshold = {threshold:.0f})")
Breakdown by model
This is the report that pays off the most, because it points to concrete action. Total cost doesn’t tell you what to do; breakdown by model does—it reveals simple tasks routed to the most expensive model, which are the easiest savings to realize on an API bill.
curl -X POST "https://management-api.x.ai/v1/billing/teams/$TEAM_ID/usage" \
-H "Authorization: Bearer $MANAGEMENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"analyticsRequest": {
"timeRange": {
"startTime": "2026-03-01 00:00:00",
"endTime": "2026-04-01 00:00:00",
"timezone": "UTC"
},
"timeUnit": "MONTH",
"values": [
{"name": "tokens", "aggregation": "SUM"},
{"name": "cost", "aggregation": "SUM"}
],
"groupBy": ["model"]
}
}'
This analysis can reveal optimization opportunities: if a large portion of your requests use grok-4.20-0309-reasoning for simple tasks, switching to grok-4.3 could significantly reduce costs.
Automated weekly report
Automatic delivery changes the nature of the exercise: a report you have to fetch is only consulted after the incident, a report that arrives is read beforehand. Weekly is the right cadence for API consumption—frequent enough to catch drift before the bill, spaced enough that you keep opening it.
import requests
from datetime import datetime, timedelta
MANAGEMENT_API = "https://management-api.x.ai"
MGMT_KEY = "xai-mgmt-..."
TEAM_ID = "team-..."
# Previous week
end = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
start = end - timedelta(days=7)
response = requests.post(
f"{MANAGEMENT_API}/v1/billing/teams/{TEAM_ID}/usage",
headers={
"Authorization": f"Bearer {MGMT_KEY}",
"Content-Type": "application/json"
},
json={
"analyticsRequest": {
"timeRange": {
"startTime": start.strftime("%Y-%m-%d %H:%M:%S"),
"endTime": end.strftime("%Y-%m-%d %H:%M:%S"),
"timezone": "Europe/Paris"
},
"timeUnit": "DAY",
"values": [
{"name": "tokens", "aggregation": "SUM"},
{"name": "requests", "aggregation": "COUNT"}
],
"groupBy": ["model"]
}
}
)
report = response.json()
print(f"=== Weekly Report {start.date()} → {end.date()} ===")
# Format report for email/Slack
# ... send via your preferred notification tool
Granularity and performance
Choosing the right granularity
| Use case | Recommended granularity |
|---|---|
| Monthly report | MONTH |
| Daily tracking | DAY |
| Spike analysis | HOUR or QUARTER_HOUR |
| Real-time debug | MINUTE |
| Detailed incident analysis | SECOND |
The finer the granularity, the larger the amount of data returned: over a month, SECOND granularity produces millions of points, with corresponding response time and memory consumption. The rule of thumb is to choose granularity based on the duration of what you’re looking for—a few-minute spike is invisible at MONTH granularity, and drowned in noise at SECOND granularity.
Key takeaways
- Combine
SUM(total),COUNT(count), andgroupBy: ["model"]for complete reports - Anomaly detection with standard deviation identifies overconsumption days
- Breakdown by model reveals cost optimization opportunities
- Adapt temporal granularity to the use case: MONTH for reports, HOUR for debug
- Automate weekly reports to keep an eye on consumption