Usage
/v1/usage exposes the calling account’s current calendar-month (UTC)
totals + tier quotas. /v1/usage/series returns a daily-bucketed
sparkline for the last N days.
Both endpoints honor the X-Driftstack-Account header (Team RBAC):
when set to a team owner’s account id, the response covers the
OWNER’s usage rather than the calling member’s. The owner’s tier is
the quota-cap source — being on a team doesn’t bump a member’s
personal cap.
Current period summary
GET /v1/usage
Response (200):
{
"period_start": "2026-05-01T00:00:00.000Z",
"period_end": "2026-06-01T00:00:00.000Z",
"tier": "pro_v3",
"totals": {
"session_minute": 1234,
"navigate": 56789,
"interact": 12345,
"wait": 6789,
"state_capture": 234,
"screenshot_capture": 78
},
"quotas": {
"session_minute": null,
"navigate": null,
"interact": null,
"wait": null,
"state_capture": null,
"screenshot_capture": null
}
}
Fields
period_start/period_end— UTC ISO 8601. The current calendar month bounds (period_end is exclusive — the first second of the next month).tier— the account’s billing tier. The tier determines the quota caps below.totals.*andquotas.*use the same key set — theUsageRecordTypeenum (singular):session_minute,navigate,interact,wait,state_capture,screenshot_capture. Both maps always carry all six keys.totals.session_minute— wall-clock minutes sessions were active, summed across the calendar month. No paid plan caps it. The Trial has a 120-minute total for the whole trial, shown inquotas.session_minutebelow.totals.navigate/interact/wait— count of each session action you invoked. Free on all tiers; shown for your information.totals.state_capture/screenshot_capture— count of state reads + screenshot endpoint hits. Same: count-only, no per-tier cap.quotas.session_minute—nullon every PAID plan, and120on the Trial. Paid plans are priced on concurrent sessions only, so they carry no cap on minutes; the field is preserved on them (rather than removed) so the response shape stays stable. On the Trial the figure is the session time the WHOLE trial includes, and it is enforced. It is counted from the day the trial starts, across every session the account runs — not per calendar month like thetotalshere — so on a trial that crosses a month boundary,totals.session_minuteshows only the current month’s part.quotas.<other>isnullfor record types that are unmetered (the operation-count meters are free / count-only). A non-null value here would mean a hard cap exists; cross-check againsttotals.<same-key>to see how much headroom remains.
quotas.session_minute is null on every paid plan: no paid plan
meters session minutes or has a monthly total of hours. A single session
still ends on its own: at 4 hours when it was started in manual mode (every
POST /v1/sessions session through a proxy, every profile launch, and manual
sessions from the desktop app), and no later than about 12 hours after it was
created in every other case. A session left unused closes sooner.
The Trial has a total and a shorter session limit: it includes 120
minutes of session time in total, and a single trial session is closed after
20 minutes. A new trial session runs for 20 minutes or for what is left
of the total, whichever is shorter. A session still running when the
total runs out is closed with closed_reason: "trial_time_used", and
once none is left, creating a session is refused with 429
tier-limit (code: "trial_session_time_used").
This endpoint does not surface the concurrent-sessions cap or the profile-count cap — those are tier-table values enforced at create time. See /reference/rate-limits for the full per-tier configuration.
Daily series
GET /v1/usage/series?days=30
Response (200):
{
"from_date": "2026-04-09",
"to_date": "2026-05-09",
"buckets": [
{
"date": "2026-04-09",
"totals": {
"session_minute": 42,
"navigate": 1200,
"interact": 350,
"wait": 75,
"state_capture": 8,
"screenshot_capture": 3
}
}
]
}
totals is a record keyed by record type (singular form, matching
the UsageRecordType enum + the field names on the
current_period totals). days parameter: 1-90, default 30.
The series is right-aligned on “yesterday” (the most-recent
fully-closed UTC day); today’s partial bucket is intentionally
not surfaced — the dashboard’s sparkline renders cleaner without
a half-empty trailing bucket.
Empty days are included in the series (not omitted from the
response) so the dashboard can render an empty-state without
client-side date-fill logic, but their totals is an empty object
{} — treat a missing counter key as 0. (The current-period
summary, by contrast, zero-fills every counter.)
SDK usage:
const series = await client.usage.series({ days: 30 });
for (const b of series.buckets) {
console.log(b.date, b.totals.session_minute, b.totals.navigate);
}
series = client.usage.series(days=30)
for b in series["buckets"]:
print(b["date"], b["totals"].get("session_minute", 0))
series, _ := client.Usage.Series(ctx, 30)
for _, b := range series.Buckets {
fmt.Println(b.Date, b.Totals["session_minute"], b.Totals["navigate"])
}
Quota / tier caps
Each plan has a fixed limit on concurrent sessions and saved profiles
(the public @driftstack/api-types package also exports them as
TIER_CONCURRENT_SESSION_LIMITS and PROFILES_PER_TIER):
| Plan | Tier id | Concurrent sessions | Profiles |
|---|---|---|---|
| Trial | trial |
1 | 1 |
| Starter | starter_v3 |
1 | 25 |
| Pro | pro_v3 |
3 | 100 |
| Team | team_v3 |
6 | 300 |
| Scale | scale_v3 |
12 | 1,000 |
| Enterprise | enterprise |
20+ | Unlimited |
Enterprise limits are set by contract.
The earlier plans, no longer offered, keep their limits for the accounts that hold them:
| Plan | Tier id | Concurrent sessions | Profiles |
|---|---|---|---|
| Personal | solo_manual |
1 | 10 |
| Team | team_manual |
3 | 50 |
| Agency | agency_manual |
8 | 200 |
| API Starter | api_starter |
2 | 25 |
| API Builder | api_builder |
8 | 100 |
| API Scale | api_scale |
24 | 500 |
Paid plans are priced on how many sessions run at once. There is no
monthly total of session hours (fair use), no session-minute meter and
no per-meter overage billing. One session does not run for ever: a session
started in manual mode ends at 4 hours, and any session still open about 12
hours after it was created is closed. The Trial includes 2 hours of session
time in total, counted from the day it starts, and caps a single
session at 20 minutes; both are enforced. The operation counters (navigate /
interact / wait / state_capture / screenshot_capture) are
shown for your information and are never charged.
Auth + scoping
Both endpoints accept any valid bearer (API key OR web session)
with read scope. The X-Driftstack-Account header is honored for
team scopes — member roles read the owner’s usage.
Errors
| Status | Body type | When |
|---|---|---|
| 401 | unauthorized |
Missing / invalid bearer |
| 403 | forbidden |
X-Driftstack-Account points at an account the caller isn’t a member of |
| 400 | validation-failed |
days outside [1, 90] on /series |
Historical data
Usage history starts from the date usage tracking launched. Days
before that show as zero in the dashboard and in /series results.
This is expected and does not mean data is missing.