Export usage
For: tenant administrators and cost owners.
Export recorded calls and charges for reporting and chargeback.
Usage export
usage export writes a tenant's usage for a period as CSV or JSON lines, in a schema that stays the same from one
release to the next, for a finance tool, a data warehouse or your own reports:
oz0 usage export --from 2026-10-01 --to 2026-11-01 --format csv --out october.csv
oz0 usage export --from 2026-10-01 --to 2026-10-02 --format jsonl
oz0 usage export --all-tenants --from 2026-10-01 --to 2026-11-01 --format jsonl --out all.jsonl
--from is the first UTC day and --to the day after the last, at most 400 days apart. The tenant's admins may
export; --all-tenants needs a cluster admin. Each export is audited (usage.export, with who, the tenant and the
period). --out writes the file with mode 0600, and only once the whole export has arrived: an export that fails
leaves no file. A long export streams for as long as it needs, up to --timeout (an hour unless you say otherwise;
0 for no limit). The admin API's ExportUsage streams the same rows.
There is one row per model call or plugin report and unit kind, and per day of outside spend:
| Column | What it holds |
|---|---|
schema_version | 1, on every row |
row_id | The same in every export of the row: <usage id>:<unit kind>, or outside:<hash>:<unit kind> |
charge_period | The UTC day it was metered on, YYYY-MM-DD |
source | gateway (a model call), plugin:<name> (a plugin's report) or outside:<plugin> (outside spend; outside alone for teams works-council mode hides) |
tenant, team | The tenant, and the team the job was charged to; empty for none |
tags | The job's tags when the call was made, a JSON array |
job, agent | The job (a child job's own ID) and the agent |
provider, model, region | The provider record, the model, and the region the record named at the time of the call; for a plugin's report, the service it paid and its unit |
unit_kind | input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, web_searches, compute_seconds, plugin_units, or charge |
unit, quantity | The unit (tokens, searches, seconds, a plugin's own unit, call or day) and how many |
list_cost | What it costs at the provider's published list price |
effective_cost | What it cost the tenant: the price it was metered at, the record's own price where it has one, cache prices included |
currency | USD for everything Orchestrator Zero metered; outside spend keeps the provider's currency |
attributes_recorded | false when the row's team and tags are not known: rows written before the export's columns were recorded, and calls whose job could not be read at the time |
member | The member of a pooled provider record that served the call, such as sweden; empty for other records and for rows written before pools |
plugin | The plugin whose tool asked for the model call: its MCP sampling request, its call's gateway token or a uses_model key, such as notes; empty for an agent's own calls, for plugins' reports and for rows written before the column |
Costs and missing prices
Costs are decimals with six places, exact to the micro-dollar; empty in CSV and null in JSON when not known.
The effective costs of a call's rows add up to the call's cost. A cost the price source gives only as a whole, such
as a provider's own reported cost, goes on a charge row (quantity 1), and that call's token rows have no cost of
their own. A list cost is known when the public price list knows the model: a node's local model, a plugin's report
and outside spend have none.
Recording dates and stable attributes
A period is the days the calls were recorded in, by the database's clock when management took the row: a call
an edge held while management was away, or one made just before midnight, is in the day it arrived, with its
charge_period still the day it was made. So exporting a period that has passed again gives the same rows (until
the retention of usage rows deletes them).
Region, team, tags, the list cost and the split by kind are recorded when the call is made, so exporting a
period again gives the same rows (until the retention of usage rows deletes them). Rows
written before they were recorded keep them empty, with attributes_recorded false and their cost on a charge
row; they are never filled in from today's records.
A call whose job could not be read when it was made, such as
while management was away from an edge, keeps its region and costs but has attributes_recorded false: its team
and tags are unknown, not none.
A job's team and tags are its root job's: a child job is charged where its parent is, and a job ID started again by someone else is theirs from its first call.
Erasure
A person's erasure empties the tags on the usage rows of the erased jobs, since a tag can name a person. The rows stay, with their IDs, team and costs, so the next export shows them without tags.
Pooled calls
A call to a pooled provider record is one row per unit kind however many members it tried: a member that
answered 429 before any output is not charged, and the row names the member that served it, at that member's price
(its own --price where it has one). Budgets, quotas and chargeback count the call once.
Team visibility
Nothing names a person. There is no column for who started a job. Under
works-council mode a team appears only where its figures may be shown to you, and
the row is otherwise the tenant's, with an empty team.
Schema and spreadsheet compatibility
A later release may add columns at the end of a row; removing or renaming a column, or changing what
one holds, makes a new schema_version. CSV cells that start with =, +, - or @ get a leading ', so a
spreadsheet does not read them as formulas.