---
title: "Export usage"
description: "Export recorded calls and charges for reporting and chargeback."
canonical_url: "https://docs.oz0.ai/spend/cost-and-usage/exports"
---
# Export usage

> Export recorded calls and charges for reporting and chargeback.

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:

```bash [Terminal]
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:

<table>
<thead>
  <tr>
    <th>
      Column
    </th>
    
    <th>
      What it holds
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        schema_version
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
      
      , on every row
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        row_id
      </code>
    </td>
    
    <td>
      The same in every export of the row: <code>
        &lt;usage id>:&lt;unit kind>
      </code>
      
      , or <code>
        outside:&lt;hash>:&lt;unit kind>
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        charge_period
      </code>
    </td>
    
    <td>
      The UTC day it was metered on, <code>
        YYYY-MM-DD
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        source
      </code>
    </td>
    
    <td>
      <code>
        gateway
      </code>
      
       (a model call), <code>
        plugin:&lt;name>
      </code>
      
       (a plugin's <a href="https://docs.oz0.ai/spend/cost-and-usage/accounting#costs-that-plugins-report">
        report
      </a>
      
      ) or <code>
        outside:&lt;plugin>
      </code>
      
       (<a href="https://docs.oz0.ai/spend/cost-and-usage/accounting#outside-spend">
        outside spend
      </a>
      
      ; <code>
        outside
      </code>
      
       alone for teams works-council mode hides)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tenant
      </code>
      
      , <code>
        team
      </code>
    </td>
    
    <td>
      The tenant, and the team the job was charged to; empty for none
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tags
      </code>
    </td>
    
    <td>
      The job's <a href="https://docs.oz0.ai/improve/errors-and-insights#search-and-tags">
        tags
      </a>
      
       when the call was made, a JSON array
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        job
      </code>
      
      , <code>
        agent
      </code>
    </td>
    
    <td>
      The job (a child job's own ID) and the agent
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        provider
      </code>
      
      , <code>
        model
      </code>
      
      , <code>
        region
      </code>
    </td>
    
    <td>
      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
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        unit_kind
      </code>
    </td>
    
    <td>
      <code>
        input_tokens
      </code>
      
      , <code>
        output_tokens
      </code>
      
      , <code>
        cache_read_tokens
      </code>
      
      , <code>
        cache_write_tokens
      </code>
      
      , <code>
        web_searches
      </code>
      
      , <code>
        compute_seconds
      </code>
      
      , <code>
        plugin_units
      </code>
      
      , or <code>
        charge
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        unit
      </code>
      
      , <code>
        quantity
      </code>
    </td>
    
    <td>
      The unit (<code>
        tokens
      </code>
      
      , <code>
        searches
      </code>
      
      , <code>
        seconds
      </code>
      
      , a plugin's own unit, <code>
        call
      </code>
      
       or <code>
        day
      </code>
      
      ) and how many
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        list_cost
      </code>
    </td>
    
    <td>
      What it costs at the provider's published list price
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        effective_cost
      </code>
    </td>
    
    <td>
      What it cost the tenant: the price it was metered at, the record's own price where it has one, cache prices included
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        currency
      </code>
    </td>
    
    <td>
      <code>
        USD
      </code>
      
       for everything Orchestrator Zero metered; outside spend keeps the provider's currency
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        attributes_recorded
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
      
       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
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        member
      </code>
    </td>
    
    <td>
      The member of a <a href="https://docs.oz0.ai/spend/models-and-keys/deployment-pools#pools-of-deployments">
        pooled provider record
      </a>
      
       that served the call, such as <code>
        sweden
      </code>
      
      ; empty for other records and for rows written before pools
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        plugin
      </code>
    </td>
    
    <td>
      The plugin whose tool asked for the model call: its <a href="https://docs.oz0.ai/build/parts/tools/model-calls#tools-that-need-a-model">
        MCP sampling request, its call's gateway token
      </a>
      
       or a <code>
        uses_model
      </code>
      
       key, such as <code>
        notes
      </code>
      
      ; empty for an agent's own calls, for plugins' reports and for rows written before the column
    </td>
  </tr>
</tbody>
</table>

### 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](https://docs.oz0.ai/govern/audit-trail) 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](https://docs.oz0.ai/govern/audit-trail) 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](https://docs.oz0.ai/govern/personal-data/erase#erase) 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](https://docs.oz0.ai/govern/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.


## Sitemap

See the full [sitemap](https://docs.oz0.ai/sitemap.md) for all pages.
