Usage
Monitor request volume, token consumption and performance in detail. The page's eyebrow reads Analytics and its heading is Usage.
Choosing whose usage to view
A My Usage / Team Usage toggle sits at the top of the page. It defaults to My Usage, and Team Usage is available only to organization admins and owners. Team Usage widens every figure on the page to the whole organization and reveals the Organization Users Usage table.
One API key at a time
This page scopes usage to a person or to the whole organization. To read the same board for a single credential, open API Keys and use the Analytics action on the key's row. The metrics, the ranges and the tables are the same ones described here, narrowed to that one key. See Key Analytics.
Choosing a date range
Five range pills sit above the metrics:
Today · 7D · 30D · 90D · Custom
The default is 30D. The 7, 30 and 90 day pills are exact calendar ranges aligned to your active timezone, not approximate rolling windows, so opening the same pill twice returns the same period.
There is no Yesterday pill and no Last 24 hours pill. Both windows are available, but as fixed ranges inside the Custom popover.
Custom range
Selecting Custom opens a split-panel popover so you can pick a window whichever way is fastest:
- Quick ranges (left): a "Last [N] ⟨unit⟩" builder (minutes, hours, days, weeks, months, years) plus one-click fixed ranges such as This week and This month. Choosing one fills the custom range on the right.
- Custom range (right): a timezone badge, collapsed FROM and TO date-time fields, a live summary of the window, and Apply.
Each FROM/TO field opens a compact calendar for the date and an HH:mm field for the time (24-hour), so you can narrow usage to an incident window ("between 14:30 and 16:00 today") rather than only whole days.
- Time errors appear on blur only, so you are not warned mid-keystroke; an invalid time such as
25:70is rejected. - Nested popovers close innermost-first: Escape or an outside click closes the open calendar or time popover before the whole picker.
- Ranges are capped to the last 365 days. A longer quick range such as "Last 2 years" is clamped, with a "Limited to the last 365 days" note.
The outer preset pills remain date-only; the whole end-of-day is included automatically.
Dates, times and preset day boundaries resolve against your browser's local timezone, and the picker displays the timezone it is using. An explicit, non-UTC timezone on your profile takes precedence over the browser. A profile timezone of literally UTC is treated as unset and falls back to the browser.
Chart granularity
Granularity is derived from the range you pick rather than fixed:
| Range length | Points |
|---|---|
| Up to 7 days | Hourly |
| Up to 90 days | Daily |
| Longer | Weekly |
Daily, weekly and monthly points are cut on your local day boundaries, daylight-saving transitions included, so traffic just before local midnight is charted on the day it happened rather than on the neighbouring one. Hourly points stay on UTC hours — an hour is an hour wherever you are.
Headline metrics
Eight tiles sit at the top. Each carries a delta pill comparing the selected range against the immediately preceding period of equal length, plus a sparkline.
| Tile | Meaning |
|---|---|
| Total Requests | Chat and completion calls in range |
| Total Tokens | Input plus output |
| Input Tokens | Prompt tokens |
| Output Tokens | Generated tokens |
| Request Success Rate | Share of requests that completed |
| Avg Duration | Mean end-to-end request time |
| Avg Tokens/Sec | Mean generation throughput |
| Top Model | Most-used model in range |
The caption beneath the grid states the scope of all eight:
Every figure above counts chat and completion requests, metered in tokens. Audio is metered separately, in seconds and characters, and is not counted here.
Usage over time
The chart offers a layout control: Focus, Board, or Overlay, defaulting to Focus. Focus foregrounds one measure at a time, Board lays the measures out side by side, and Overlay draws them together on shared axes.
Four measures are available: Requests, Tokens, Input tokens and Output tokens.
Insight cards
Token distribution
A donut splitting input against output tokens, with an I/O ratio footer.
Performance & cache
| Row | Meaning |
|---|---|
| Avg Latency | Mean request duration |
| Tokens / request | Mean tokens produced and consumed per call |
| Avg Tokens/Sec | Mean generation throughput |
| Cache Read | Input tokens served from the prefix cache |
| Cache hit requests | Requests that hit the cache at all |
| Cache hit rate | Share of requests that hit the cache |
Cache Read is a token count: how many prompt tokens were served from the prefix cache. Cache hit requests and Cache hit rate count requests, and are a different measure. The same Cache Read label is used on the Dashboard token split row and in the cache popover of the Usage by Model table. Plan and pricing copy keeps its own wording — a plan's Cached $/1M rate and its cached-token quota rows refer to the same tokens under the names used on Plans and Billing.
Models with automatic prefix caching reuse the computed prefix of a prompt across requests, and cached input is charged at a reduced rate. Keep the shared or system portion of your prompts stable at the start of each request to make the cache work for you.
Audio usage
Subtitled "Speech-to-text and text-to-speech requests, metered in seconds of audio and characters of text", this card reports three measures. Each is drawn only when it is non-zero:
| Measure | Unit |
|---|---|
| Audio Requests | Calls |
| Transcribed | Seconds of input audio |
| Synthesized | Characters of input text |
The card carries this note:
Audio holds no plan quota or commitment allowance. It is measured on its own, separately from token usage.
In My Usage the card also carries an Organization-wide pill: audio totals always cover the whole organization, even in your personal view. That is a deliberate choice, not a missing number. A per-member audio figure would be partial in a way you could not detect, because audio requests only began recording which member made them partway through the platform's history and there is no way to work out the earlier ones. An organization total has no such hole, and it is the same number for every role.
When there is nothing to show, the card reads "No audio usage in the selected date range."
Speech-to-text is metered per second of input audio, rounded up, with an optional per-model minimum billed duration; a rate displayed per minute is a readability convenience, not the billing granularity. Text-to-speech is priced on the input text, per 1,000,000 characters, and a single request accepts at most 4096 characters. See Speech to Text and Text to Speech.
Tables
Usage by Model
| Column | Description |
|---|---|
| Model | Model identifier |
| Total Requests | Calls to that model |
| Input | Input tokens |
| Output | Output tokens |
| Total Tokens | Input plus output |
| Avg Latency | Mean request duration |
| Share of tokens | That model's percentage of all tokens in range |
Organization Users Usage
Visible in Team Usage only, and only to admins and owners. It lists each member with their request count, tokens, share of the organization and status.
When a member's figures cannot be read, the cell renders Not available rather than 0. An unreadable number is never displayed as an absence of usage.
Recent Activity
The most recent text requests, capped at 10 rows, with a Refresh button. There is no "view all" link; use the Export for a full history.
Export
Open the Export menu on the Usage page. Choose a format, then an option.
Formats
- Excel (.xlsx): one styled workbook with one sheet per section.
- CSV (.csv): a CSV file cannot hold multiple sheets, so the export always downloads a ZIP archive containing one CSV per sheet. Each member is numbered in sheet order and named after its sheet: a Quick Export of your personal usage produces
01_overview.csv,02_models.csvand03_daily_trends.csv. Each file keeps its own headers and a UTF-8 byte-order mark, so it opens cleanly in Excel or any spreadsheet tool.
Options
- Quick Export: "Includes Overview, Models, and Daily Trends."
- Export With History: "Adds a Usage History sheet with the most recent 5,000 rows." The detail sheet is fetched in pages and stitched together; the 5,000-row cap keeps the file performant.
In Team Usage the export also carries a Users sheet.
Nothing on the Usage screen is priced, but the exported sheets are. The Overview sheet carries Total Cost, Avg Cost / Request and Audio Cost; the Models sheet carries a per-model Cost column; the Daily Trends sheet carries a per-day Cost column. If you need priced usage as a file, this is where to get it.
The selected date range, including hour and minute when set through Custom, is preserved in the file's metadata.
Spending alerts
When you have a personal daily limit configured, the platform emails you at 80% and 90% of it. See Cost Limits.
API Reference
Get current usage
curl "https://api.bulutistan.ai/api/v1/usage/current" \
-H "Authorization: Bearer sk-proj-your-api-key"
/usage/current reports the billing period that is open now, from the instant that period opened to now. It accepts no start_date or end_date. For an arbitrary range, use /usage/tenant-breakdown or the portal's Export.
period_start is that instant, seconds included — a period opened mid-day by a plan change, a billing-mode change or a commitment renewal reports the moment it opened, not midnight. This is the same window /api/v1/plan/current and the Billing page report, so the three agree. It was previously a fixed calendar month, which matched the billing period only for organizations anchored on the 1st. See Plans.
Query parameters
| Parameter | Values | Default | Notes |
|---|---|---|---|
scope | user, tenant | user | tenant is honoured only for admins and owners. A member asking for tenant is narrowed to their own rows rather than refused. |
format | display, detail, invoice, raw | display | Controls cost precision: user-friendly, full precision, two decimals, and eight decimals respectively. |
# Organization-wide usage (admin or owner)
curl "https://api.bulutistan.ai/api/v1/usage/current?scope=tenant" \
-H "Authorization: Bearer sk-proj-your-api-key"
Response fields
tenant_id, period_start, period_end, total_requests, successful_requests, failed_requests, success_rate, total_input_tokens, total_output_tokens, total_tokens, total_cached_tokens, cache_hit_requests, average_tokens_per_request, total_cost, total_cache_savings, average_cost_per_request, average_cost_per_token, total_cost_formatted, average_cost_per_request_formatted, average_cost_per_token_formatted, currency, average_duration_ms, models_used, top_model, models_breakdown, audio.
{
"tenant_id": "c63f88b3-cb39-4f07-8353-4982557f7533",
"period_start": "2026-08-01T00:00:00",
"period_end": "2026-08-14T09:30:00",
"total_requests": 1250,
"successful_requests": 1200,
"failed_requests": 50,
"success_rate": 0.96,
"total_input_tokens": 125000,
"total_output_tokens": 85000,
"total_tokens": 210000,
"total_cached_tokens": 18000,
"cache_hit_requests": 210,
"average_tokens_per_request": 168.0,
"total_cost": "45.50000000",
"total_cost_formatted": "$45.50",
"currency": "USD",
"average_duration_ms": 850.0,
"models_used": ["your-chat-model"],
"top_model": "your-chat-model",
"models_breakdown": [
{
"model_name": "your-chat-model",
"requests": 1250,
"input_tokens": 125000,
"output_tokens": 85000,
"total_tokens": 210000,
"total_cost": 45.5,
"avg_duration_ms": 850.0
}
]
}
audio may be absentThe audio block is omitted from the payload entirely (not returned as null) when there is no audio usage, and it is populated only on a tenant-scoped read. Its absence from a personal-scope response does not mean your organization sent no audio traffic. Read audio totals with scope=tenant.
Get usage history
Individual usage events, most recent first.
curl "https://api.bulutistan.ai/api/v1/usage/history?api_key_id=<key-id>&limit=50" \
-H "Authorization: Bearer sk-proj-your-api-key"
Alongside the date, model, endpoint, limit and offset filters, api_key_id narrows the feed to the events produced by one API key. Every returned event carries its own api_key_id, so you can attribute a request to the credential that made it without filtering first.
Get per-user breakdown
Admin or owner only.
curl "https://api.bulutistan.ai/api/v1/usage/tenant-breakdown" \
-H "Authorization: Bearer sk-proj-your-api-key"
Accepts start_date, end_date and timezone. The requested range may span at most 90 days.
{
"tenant_id": "c63f88b3-cb39-4f07-8353-4982557f7533",
"period": {
"start_date": "2026-07-01T00:00:00",
"end_date": "2026-07-31T23:59:59"
},
"users": [
{
"user_id": "uuid-1",
"total_requests": 500,
"input_tokens": 80000,
"output_tokens": 20000,
"total_tokens": 100000,
"total_cost": 20.0,
"successful_requests": 490,
"failed_requests": 10
}
],
"tenant_total": {
"total_requests": 800,
"total_tokens": 160000,
"total_cost": 32.0
}
}
Users are returned sorted by cost, highest first.
Python example
import requests
api_key = "sk-proj-your-api-key"
base_url = "https://api.bulutistan.ai"
headers = {"Authorization": f"Bearer {api_key}"}
usage = requests.get(
f"{base_url}/api/v1/usage/current",
headers=headers,
params={"scope": "tenant", "format": "display"},
).json()
print(f"Requests: {usage['total_requests']}")
print(f"Tokens: {usage['total_tokens']}")
print(f"Top model: {usage['top_model']}")
# `audio` is omitted when there is none, so ask for it defensively.
audio = usage.get("audio")
if audio:
print(f"Audio: {audio}")