Reporting usage across companies
Plenty of questions come down to one number per company: how much of a metered feature did they use between these two dates. Who is pushing their limit and ready for an upgrade conversation, which accounts grew month over month, what does the usage distribution look like. GET /feature-usage-history answers that, one row per company, per feature, per period.
Prefer this over GET /feature-usage-timeseries. Its points are cumulative within the billing period, so summing them double counts. Feature usage history reports incremental usage, so its rows can be summed.
Getting a month
Ask for the window and read the rows.
Each row carries:
This endpoint scans every company in the environment, so it requires a secret API key (sch_ prefix). Publishable keys and the Stripe app are deliberately shut out. See Authentication.
The start is included, the end is not
June is 2026-06-01T00:00:00Z to 2026-07-01T00:00:00Z, which covers all of June and nothing in July. Usage recorded at exactly midnight on July 1 belongs to July. That is what lets you run twelve consecutive months and have them tile with no gaps and nothing counted twice.
Both bounds must land on an hour boundary in UTC. Usage is measured hourly, so an off-hour bound is rejected rather than rounded, and the error names whichever end is wrong. We would rather fail loudly than quietly shift the window you asked for.
Event features only
Usage over a date range is only meaningful for features that measure events. Trait and boolean feature IDs return a 400 telling you so.
A company with no usage is absent, not zero
If a company recorded no events in the window, it has no row in the response. It does not appear with usage: 0.
So the response tells you who used the feature, not who exists. If you need the full picture, including the accounts that used nothing, iterate your own list of companies and treat a missing company as zero.
Bucketing with granularity
Omit granularity and you get a single total per company and feature covering the whole window. That is what a ranking or a one-off total wants.
Pass hourly, daily, weekly, or monthly to break the window into buckets, with one row per company, per feature, per bucket.
A single request may span at most 366 buckets. That is a year of days, or roughly two weeks of hours. Longer requests are rejected; ask for a shorter range or a coarser granularity.
Paging
Default page size is 100 and the maximum is 250. Page by raising offset until a page comes back empty.
Advance offset by limit, not by the number of rows you received.
Where two features measure the same event key, both are reported, so a page can come back with more rows than the limit you asked for. Paging happens before that fan-out. Rows are never dropped or repeated, but a loop that advances by page.data.length will skip some.
Worked example: finding upgrade candidates
Pull last month for one feature, sum per company, and rank. The companies at the top are the ones leaning hardest on the feature, which is where an upgrade conversation starts.
listFeatureUsageHistory requires @schematichq/schematic-typescript-node 1.5.9 or newer. Earlier releases predate the endpoint and do not have the method. Other SDKs may need a release cut before it appears.
Related
- Creating a metered feature, for setting up the event features this reports on
- Backfills and usage corrections, for importing historical usage or fixing events that arrived late
- Usage-based billing