[Objects](https://oods-foundry.com/objects) / Usage

# Usage

Metered usage snapshot for consumption based billing supporting trend analysis and overage forecasting.

beta 3 traits · 7 contexts · 25 fields [Usage.object.yaml](#file) [How objects work](https://oods-foundry.com/guides/objects-and-traits)

Generated from @oods/foundry 0.10.1

This object is marked beta.

## Screens

Every screen below was generated from this object by OODS Foundry 0.10.1, in React and Vue, and shows the calls that made it and its content hash. Each runs as its generated app runs, in this site's brand, Aquex, in the theme you choose, with the sample records this object's own file carries. A value no record gives shows as a neutral one, such as an empty value or "Not recorded"; OODS Foundry invents none.

[Usage detail screen generated by OODS Foundry in React](https://oods-foundry.com/objects/usage/screens/detail-react)

React app · sample records Maturity: beta `sha256:59cecc5ee6fa…` [Open full size: Usage detail screen generated by OODS Foundry in React](https://oods-foundry.com/objects/usage/screens/detail-react)

Vue app · sample records Maturity: beta `sha256:ab080c969bc8…` [Open full size: Usage detail screen generated by OODS Foundry in Vue](https://oods-foundry.com/objects/usage/screens/detail-vue)

React app · sample records Maturity: beta `sha256:da3d08d651c7…` [Open full size: Usage list screen generated by OODS Foundry in React](https://oods-foundry.com/objects/usage/screens/list-react)

Vue app · sample records Maturity: beta `sha256:9c39aa0180a3…` [Open full size: Usage list screen generated by OODS Foundry in Vue](https://oods-foundry.com/objects/usage/screens/list-vue)

React app · sample records Maturity: beta `sha256:274d14d07575…` [Open full size: Usage form screen generated by OODS Foundry in React](https://oods-foundry.com/objects/usage/screens/form-react)

Vue app · sample records Maturity: beta `sha256:bf30892f2a99…` [Open full size: Usage form screen generated by OODS Foundry in Vue](https://oods-foundry.com/objects/usage/screens/form-vue)

React app · sample records Maturity: beta `sha256:03d0da45c96f…` [Open full size: Usage timeline screen generated by OODS Foundry in React](https://oods-foundry.com/objects/usage/screens/timeline-react)

Vue app · sample records Maturity: beta `sha256:f84663a16acc…` [Open full size: Usage timeline screen generated by OODS Foundry in Vue](https://oods-foundry.com/objects/usage/screens/timeline-vue)

React app · sample records Maturity: beta `sha256:3afadf52dd30…` [Open full size: Usage card screen generated by OODS Foundry in React](https://oods-foundry.com/objects/usage/screens/card-react)

Vue app · sample records Maturity: beta `sha256:4f83711d3108…` [Open full size: Usage card screen generated by OODS Foundry in Vue](https://oods-foundry.com/objects/usage/screens/card-vue)

React app · sample records Maturity: beta `sha256:0a6bbd84824b…` [Open full size: Usage inline screen generated by OODS Foundry in React](https://oods-foundry.com/objects/usage/screens/inline-react)

Vue app · sample records Maturity: beta `sha256:30ffac29b02c…` [Open full size: Usage inline screen generated by OODS Foundry in Vue](https://oods-foundry.com/objects/usage/screens/inline-vue)

React app · sample records Maturity: beta `sha256:39abc373bf9d…` [Open full size: Usage workflow screen generated by OODS Foundry in React](https://oods-foundry.com/objects/usage/screens/workflow-react)

Vue app · sample records Maturity: beta `sha256:d6d99d8a97ea…` [Open full size: Usage workflow screen generated by OODS Foundry in Vue](https://oods-foundry.com/objects/usage/screens/workflow-vue)

What `design_compose` reported for every screen here:

- `OODS-V121` Object 'Usage' has maturity 'beta' — composed output may change.

The calls that made the Usage detail apps, in React and Vue

3 calls, as the pipeline sent them

```
design_compose {
  "object": "Usage",
  "context": "detail",
  "preferences": {
    "brand": "Aquex",
    "theme": "light"
  }
}

code_generate {
  "schemaRef": "compose-436cc203",
  "framework": "react",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}

code_generate {
  "schemaRef": "compose-436cc203",
  "framework": "vue",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}
```

The React app's content hash: `sha256:59cecc5ee6fa8e9bd950b599b7adad7fa7f4b1ab13c15d1da17fafcf8799cb64`. Its `src/` folder: App.tsx, GeneratedUI.tsx, app.css, charts/, main.tsx, oods-brand-aquex.css

The Vue app's content hash: `sha256:ab080c969bc853355d5c6f1e13269b33cbd0b6b54412459b0188717ade723ce2`. Its `src/` folder: App.vue, GeneratedUI.vue, app.css, charts/, main.ts, oods-brand-aquex.css

The calls that made the Usage list apps, in React and Vue

3 calls, as the pipeline sent them

```
design_compose {
  "object": "Usage",
  "context": "list",
  "preferences": {
    "brand": "Aquex",
    "theme": "light"
  }
}

code_generate {
  "schemaRef": "compose-696b79d7",
  "framework": "react",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}

code_generate {
  "schemaRef": "compose-696b79d7",
  "framework": "vue",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}
```

The React app's content hash: `sha256:da3d08d651c734ed5142df4c9f2a3ef9e8f0838fc8dd1cbff4ef75603cf017a8`. Its `src/` folder: App.tsx, GeneratedUI.tsx, app.css, main.tsx, oods-brand-aquex.css

The Vue app's content hash: `sha256:9c39aa0180a388830bb556d83fb2dafcd806b2bb58cafdfe4fb6f0aac64cd197`. Its `src/` folder: App.vue, GeneratedUI.vue, app.css, main.ts, oods-brand-aquex.css

For this screen it also reported:

- `OODS-V119` No view_extensions found for context "form" in object "Usage". Available contexts: detail, list, dashboard

The calls that made the Usage form apps, in React and Vue

3 calls, as the pipeline sent them

```
design_compose {
  "object": "Usage",
  "context": "form",
  "preferences": {
    "brand": "Aquex",
    "theme": "light"
  }
}

code_generate {
  "schemaRef": "compose-f56807d3",
  "framework": "react",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}

code_generate {
  "schemaRef": "compose-f56807d3",
  "framework": "vue",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}
```

The React app's content hash: `sha256:274d14d07575bf5a422851070efbf8350a84147555cbd14434fefb20afb62e22`. Its `src/` folder: App.tsx, GeneratedUI.tsx, app.css, main.tsx, oods-brand-aquex.css

The Vue app's content hash: `sha256:bf30892f2a99ab49405047120fdf2ee2b17950492cb4cb1dd20a31b9286db31d`. Its `src/` folder: App.vue, GeneratedUI.vue, app.css, main.ts, oods-brand-aquex.css

For this screen it also reported:

- `OODS-V119` No view_extensions found for context "timeline" in object "Usage". Available contexts: detail, list, dashboard

The calls that made the Usage timeline apps, in React and Vue

3 calls, as the pipeline sent them

```
design_compose {
  "object": "Usage",
  "context": "timeline",
  "preferences": {
    "brand": "Aquex",
    "theme": "light"
  }
}

code_generate {
  "schemaRef": "compose-f9fbb041",
  "framework": "react",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}

code_generate {
  "schemaRef": "compose-f9fbb041",
  "framework": "vue",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}
```

The React app's content hash: `sha256:03d0da45c96f564e3857c785d9136c5787e9db2da03da58b2d1ebb3ea4b2d341`. Its `src/` folder: App.tsx, GeneratedUI.tsx, app.css, main.tsx, oods-brand-aquex.css

The Vue app's content hash: `sha256:f84663a16acc81e00e9974c054bafa08f17888378b2e998d08e5c63422910790`. Its `src/` folder: App.vue, GeneratedUI.vue, app.css, main.ts, oods-brand-aquex.css

For this screen it also reported:

- `OODS-V119` No view_extensions found for context "card" in object "Usage". Available contexts: detail, list, dashboard

The calls that made the Usage card apps, in React and Vue

3 calls, as the pipeline sent them

```
design_compose {
  "object": "Usage",
  "context": "card",
  "preferences": {
    "brand": "Aquex",
    "theme": "light"
  }
}

code_generate {
  "schemaRef": "compose-fd4cf61d",
  "framework": "react",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}

code_generate {
  "schemaRef": "compose-fd4cf61d",
  "framework": "vue",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}
```

The React app's content hash: `sha256:3afadf52dd302b9b1bffcf677b9d63ef98bb2f09e081751318ef179917205c61`. Its `src/` folder: App.tsx, GeneratedUI.tsx, app.css, main.tsx, oods-brand-aquex.css

The Vue app's content hash: `sha256:4f83711d3108da883dab451bbe632e811b796663adbb50212172bd707cf4d19b`. Its `src/` folder: App.vue, GeneratedUI.vue, app.css, main.ts, oods-brand-aquex.css

For this screen it also reported:

- `OODS-V119` No view_extensions found for context "inline" in object "Usage". Available contexts: detail, list, dashboard

The calls that made the Usage inline apps, in React and Vue

3 calls, as the pipeline sent them

```
design_compose {
  "object": "Usage",
  "context": "inline",
  "preferences": {
    "brand": "Aquex",
    "theme": "light"
  }
}

code_generate {
  "schemaRef": "compose-ebc51cd1",
  "framework": "react",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}

code_generate {
  "schemaRef": "compose-ebc51cd1",
  "framework": "vue",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}
```

The React app's content hash: `sha256:0a6bbd84824bd220a62ff46dee5c38bcda0887eda45da1cbac5b9527df727333`. Its `src/` folder: App.tsx, GeneratedUI.tsx, app.css, main.tsx, oods-brand-aquex.css

The Vue app's content hash: `sha256:30ffac29b02ce5ba1eda3d05b34d30ccc12dcac272752340c239c51995903546`. Its `src/` folder: App.vue, GeneratedUI.vue, app.css, main.ts, oods-brand-aquex.css

For this screen it also reported:

- `OODS-V121` as above, 4 times in all
- `OODS-V119` No view_extensions found for context "form" in object "Usage". Available contexts: detail, list, dashboard
- `OODS-V119` No view_extensions found for context "timeline" in object "Usage". Available contexts: detail, list, dashboard

The calls that made the Usage workflow apps, in React and Vue

3 calls, as the pipeline sent them

```
design_compose {
  "object": "Usage",
  "context": "workflow",
  "preferences": {
    "brand": "Aquex",
    "theme": "light"
  }
}

code_generate {
  "schemaRef": "compose-2e7f73df",
  "framework": "react",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}

code_generate {
  "schemaRef": "compose-2e7f73df",
  "framework": "vue",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}
```

The React app's content hash: `sha256:39abc373bf9dca0d9152842122c534e027a935b5d01547dc96ff3ae6e893e990`. Its `src/` folder: App.tsx, actions.ts, app.css, application.ts, chart-assets.ts, charts/, main.tsx, oods-brand-aquex.css, sample-data.ts, screens/, ssr.tsx, store.ts

The Vue app's content hash: `sha256:d6d99d8a97eae4fe5902ad4113addd53641795d2a89e52fa10f9903791c8a94b`. Its `src/` folder: App.vue, actions.ts, app.css, application.ts, chart-assets.ts, charts/, main.ts, oods-brand-aquex.css, sample-data.ts, screens/, ssr.ts, store.ts

## Fields

| Field | Type | Description |
| - | - | - |
| `meter_name` required | string | Friendly metered feature name shown in UI (ex: Analytics Seats). |
| `included_quantity` required | integer | Quantity included in base plan before overages. |
| `consumed_quantity` required | integer | Actual quantity consumed in the active period. |
| `unit_label` required | string | Label for display, defaults to the unit parameter. |
| `period_start` required | date | Date the usage accumulation window began. |
| `period_end` required | date | Date the usage accumulation window ends. |
| `rollover_strategy` | string | Strategy for unused units (inherits rolloverStrategy parameter). |
| `overage_rate_minor` | integer | Cost per additional unit expressed in minor currency units. |
| `projected_overage_minor` | integer | Forecasted overage spend derived from consumption trends. |
| `samples` | UsageSample\[] | Rolling usage measurements for charts or anomaly detection. |
| `created_at` required | datetime | Timestamp recording when the entity was first created. |
| `updated_at` | datetime | Timestamp for the most recent modification, when available. |
| `last_event` required | string | Lifecycle event associated with the most recent timestamp mutation. |
| `last_event_at` | datetime | Timestamp for the lifecycle event captured in last_event. |
| `usage_id` required | string | Identifier for this usage record. |
| `subscription_id` required | string | Subscription the usage belongs to. |
| `customer_name` | string | Customer account the usage is billed to. |
| `meter_id` required | string | Provider specific meter identifier. |
| `provider` required | string | Source provider for usage data. |
| `status` | string (ok, delayed, investigating) | Health of the usage feed (ok, delayed, investigating). |
| `trend_percent` | number | Percent delta compared to previous window. |
| `currency` | string | ISO 4217 currency the usage is billed in, the subscription's currency. |
| `variance_minor` | integer | Currency impact of usage variance calculated with overage rate. |
| `last_reported_at` required | datetime | Timestamp of the most recent provider usage payload. |
| `anomalies` | UsageAnomaly\[] | Detected anomalies with context for investigation. |

## Traits

Each trait adds fields and behaviour. Every object with the trait gets the same.

- [SaaSBillingMetered as MeterReading](https://oods-foundry.com/traits/saas-billing-metered)
- [Timestampable as UsageAudit](https://oods-foundry.com/traits/timestampable)
- [MarkLine](https://oods-foundry.com/traits/mark-line)

## Relationships

These arrows show declared relationships between object types. They don't join live records.

- [Subscription](https://oods-foundry.com/objects/subscription), many-to-one, via `subscription_id`

## The object file

The Usage object definition in YAML: `domains/saas-billing/objects/Usage.object.yaml`

```
object:
  name: Usage
  version: 1.0.0
  domain: saas.billing
  description: Metered usage snapshot for consumption based billing supporting trend analysis and overage forecasting.
  tags:
    - billing
    - usage
    - analytics

traits:
  - name: SaaSBillingMetered
    alias: MeterReading
    parameters:
      unit: api_calls
      rolloverStrategy: expire
      sampleWindowDays: 7
  - name: lifecycle/Timestampable
    alias: UsageAudit
    parameters:
      recordedEvents:
        - reading_captured
        - anomaly_detected
        - reset
      timezone: UTC
      allowNullUpdatedAt: true
  # s223-m01 (#2527 ruling 5): the chart is the record's own readings, its y axis titled with the record's unit label.
  - name: viz/MarkLine
    parameters:
      title: Usage readings
      description: Readings recorded for this meter, by the time each was taken.
      chart:
        chartType: line
        source: record-array
        dataField: samples
        encodings:
          x: {field: timestamp, scale: temporal, title: Recorded at}
          y: {field: value, titleField: unit_label}
        # Synthetic examples from domains/saas-billing/examples/usage-api-calls.json.
        sampleRows:
          - {timestamp: "2025-06-15T00:00:00Z", value: 1200}
          - {timestamp: "2025-06-20T00:00:00Z", value: 1800}
          - {timestamp: "2025-06-25T00:00:00Z", value: 1500}

schema:
  usage_id:
    type: string
    required: true
    description: Identifier for this usage record.
  subscription_id:
    type: string
    required: true
    description: Subscription the usage belongs to.
  customer_name:
    type: string
    required: false
    description: Customer account the usage is billed to.
  meter_id:
    type: string
    required: true
    description: Provider specific meter identifier.
  provider:
    type: string
    required: true
    description: Source provider for usage data.
  status:
    type: string
    required: false
    description: Health of the usage feed (ok, delayed, investigating).
    default: ok
    validation:
      enum:
        - ok
        - delayed
        - investigating
  trend_percent:
    type: number
    required: false
    description: Percent delta compared to previous window.
  currency:
    type: string
    required: false
    description: ISO 4217 currency the usage is billed in, the subscription's currency.
  variance_minor:
    type: integer
    required: false
    description: Currency impact of usage variance calculated with overage rate.
  last_reported_at:
    type: datetime
    required: true
    description: Timestamp of the most recent provider usage payload.
  anomalies:
    type: UsageAnomaly[]
    required: false
    description: Detected anomalies with context for investigation.
    default: []

semantics:
  # The meter names the record (SaaSBillingMetered's meter_name, marked as the label), ahead of the customer it bills.
  meter_name:
    semantic_type: text.label
    token_mapping: tokenMap(billing.usage.meter_name)
  usage_id:
    semantic_type: billing.usage.id
    token_mapping: tokenMap(billing.usage.id)
  subscription_id:
    semantic_type: billing.usage.subscription_id
    token_mapping: tokenMap(billing.usage.subscription_id)
  # The one-line summary under the meter's name in lists: whose usage it is.
  customer_name:
    semantic_type: text.summary
    token_mapping: tokenMap(billing.usage.customer_name)
  meter_id:
    semantic_type: billing.usage.meter_id
    token_mapping: tokenMap(billing.usage.meter_id)
  provider:
    semantic_type: billing.usage.provider
    token_mapping: tokenMap(billing.usage.provider)
  status:
    semantic_type: billing.usage.status
    token_mapping: tokenMap(billing.usage.status)
  trend_percent:
    semantic_type: billing.usage.trend_percent
    token_mapping: tokenMap(billing.usage.trend_percent)
    # s223-m01 (#2527 ruling 4): a percent reads with its sign (12.5%).
    ui_hints:
      format: percent
  currency:
    semantic_type: billing.usage.currency
    token_mapping: tokenMap(billing.usage.currency)
  variance_minor:
    semantic_type: billing.usage.variance_minor
    token_mapping: tokenMap(billing.usage.variance_minor)
    ui_hints:
      component: CurrencyAmount
      currencyField: currency
      minorUnits: 100
  last_reported_at:
    semantic_type: billing.usage.last_reported_at
    token_mapping: tokenMap(billing.usage.last_reported_at)
  anomalies:
    semantic_type: billing.usage.anomalies
    token_mapping: tokenMap(billing.usage.anomalies)

tokens:
  billing.usage.status.ok: "var(--cmp-badge-text-success)"
  billing.usage.status.delayed: "var(--cmp-badge-text-warning)"
  billing.usage.status.investigating: "var(--cmp-badge-text-critical)"
  billing.usage.trend_percent: "var(--cmp-text-accent)"

metadata:
  owners:
    - analytics@oods.systems
    - product-ops@oods.systems
  maturity: beta
  references:
    - R13.5 Canonical Model: Subscription and Invoice

# Authored type associations; no record join or referential-integrity claim.
relationships:
  - target: Subscription
    via: subscription_id
    cardinality: many-to-one
    label: Subscription

# Eight authored sample meter readings for the sample subscriptions, in API calls. Each reading's samples sum to its
# consumed quantity, the period is the subscription's billing period, and the last event is the latest recorded one.
# s223-m01 (#2527 ruling 4): each reading is billed in its subscription's currency, at an authored overage rate per unit.
# Its variance is the overage so far ((consumed - included) x rate, zero while within the included quantity), and its
# projected overage extends the period's pace to its end; only Kestrel's print jobs is over, and Lindqvist's catalog is
# on pace to pass its 10,000.
samples:
  - usage_id: use_northwind_orders_2026_09
    subscription_id: sub_northwind_business
    customer_name: Northwind Traders
    meter_id: mtr_orders_api
    meter_name: Orders API
    provider: Stripe
    status: ok
    trend_percent: 12.5
    included_quantity: 100000
    consumed_quantity: 86420
    currency: USD
    overage_rate_minor: 1
    variance_minor: 0
    projected_overage_minor: 0
    unit_label: API calls
    period_start: '2026-09-01'
    period_end: '2026-09-30'
    last_reported_at: '2026-09-29T23:00:00Z'
    samples:
      - { timestamp: '2026-09-07T00:00:00Z', value: 18200 }
      - { timestamp: '2026-09-14T00:00:00Z', value: 21900 }
      - { timestamp: '2026-09-21T00:00:00Z', value: 23400 }
      - { timestamp: '2026-09-28T00:00:00Z', value: 22920 }
    anomalies: []
    created_at: '2026-09-01T00:00:00Z'
    updated_at: '2026-09-29T23:00:00Z'
    last_event: reading_captured
    last_event_at: '2026-09-29T23:00:00Z'
  - usage_id: use_northwind_dashboards_2026_08
    subscription_id: sub_northwind_analytics
    customer_name: Northwind Traders
    meter_id: mtr_dashboard_queries
    meter_name: Dashboard queries
    provider: Stripe
    status: ok
    trend_percent: -41
    included_quantity: 50000
    consumed_quantity: 12480
    currency: USD
    overage_rate_minor: 2
    variance_minor: 0
    projected_overage_minor: 0
    unit_label: API calls
    period_start: '2026-08-01'
    period_end: '2026-08-31'
    last_reported_at: '2026-08-20T14:00:00Z'
    samples:
      - { timestamp: '2026-08-03T00:00:00Z', value: 4210 }
      - { timestamp: '2026-08-10T00:00:00Z', value: 4380 }
      - { timestamp: '2026-08-17T00:00:00Z', value: 3890 }
    anomalies: []
    created_at: '2026-08-01T00:00:00Z'
    updated_at: '2026-08-20T14:00:00Z'
    last_event: reading_captured
    last_event_at: '2026-08-20T14:00:00Z'
  - usage_id: use_lindqvist_catalog_2026_09
    subscription_id: sub_lindqvist_starter
    customer_name: Lindqvist Bakery
    meter_id: mtr_catalog_api
    meter_name: Catalog API
    provider: Stripe
    status: ok
    trend_percent: 38.2
    included_quantity: 10000
    consumed_quantity: 9860
    currency: EUR
    overage_rate_minor: 1
    variance_minor: 0
    projected_overage_minor: 9700
    unit_label: API calls
    period_start: '2026-09-15'
    period_end: '2026-10-14'
    last_reported_at: '2026-09-29T20:00:00Z'
    samples:
      - { timestamp: '2026-09-17T00:00:00Z', value: 2140 }
      - { timestamp: '2026-09-21T00:00:00Z', value: 2380 }
      - { timestamp: '2026-09-25T00:00:00Z', value: 2560 }
      - { timestamp: '2026-09-29T00:00:00Z', value: 2780 }
    anomalies: []
    created_at: '2026-09-15T08:00:00Z'
    updated_at: '2026-09-29T20:00:00Z'
    last_event: reading_captured
    last_event_at: '2026-09-29T20:00:00Z'
  - usage_id: use_blueharbor_webhooks_2026_09
    subscription_id: sub_blueharbor_team
    customer_name: Blue Harbor Studio
    meter_id: mtr_webhooks
    meter_name: Webhook deliveries
    provider: Stripe
    status: ok
    trend_percent: null
    included_quantity: 25000
    consumed_quantity: 3140
    currency: USD
    overage_rate_minor: 1
    variance_minor: 0
    projected_overage_minor: 0
    unit_label: API calls
    period_start: '2026-09-21'
    period_end: '2026-10-05'
    last_reported_at: '2026-09-29T22:00:00Z'
    samples:
      - { timestamp: '2026-09-22T00:00:00Z', value: 610 }
      - { timestamp: '2026-09-24T00:00:00Z', value: 880 }
      - { timestamp: '2026-09-26T00:00:00Z', value: 790 }
      - { timestamp: '2026-09-28T00:00:00Z', value: 860 }
    anomalies: []
    created_at: '2026-09-21T09:00:00Z'
    updated_at: '2026-09-29T22:00:00Z'
    last_event: reading_captured
    last_event_at: '2026-09-29T22:00:00Z'
  - usage_id: use_kestrel_printjobs_2026_09
    subscription_id: sub_kestrel_team
    customer_name: Kestrel Print Co.
    meter_id: mtr_print_jobs_api
    meter_name: Print jobs API
    provider: Stripe
    status: investigating
    trend_percent: 214
    included_quantity: 25000
    consumed_quantity: 41200
    currency: GBP
    overage_rate_minor: 5
    variance_minor: 81000
    projected_overage_minor: 159500
    unit_label: API calls
    period_start: '2026-09-03'
    period_end: '2026-10-02'
    last_reported_at: '2026-09-24T03:00:00Z'
    samples:
      - { timestamp: '2026-09-07T00:00:00Z', value: 4100 }
      - { timestamp: '2026-09-14T00:00:00Z', value: 4700 }
      - { timestamp: '2026-09-21T00:00:00Z', value: 5200 }
      - { timestamp: '2026-09-24T00:00:00Z', value: 27200 }
    anomalies:
      - { detected_at: '2026-09-24T03:00:00Z', kind: spike, description: Calls rose six-fold overnight from one API key }
    created_at: '2026-09-03T10:00:00Z'
    updated_at: '2026-09-24T03:00:00Z'
    last_event: anomaly_detected
    last_event_at: '2026-09-24T03:00:00Z'
  - usage_id: use_tidewater_reporting_2026_09
    subscription_id: sub_tidewater_enterprise
    customer_name: Tidewater Co-op
    meter_id: mtr_reporting_api
    meter_name: Reporting API
    provider: Stripe
    status: ok
    trend_percent: 4.1
    included_quantity: 1000000
    consumed_quantity: 612340
    currency: USD
    overage_rate_minor: 1
    variance_minor: 0
    projected_overage_minor: 0
    unit_label: API calls
    period_start: '2026-09-01'
    period_end: '2026-09-30'
    last_reported_at: '2026-09-29T11:00:00Z'
    samples:
      - { timestamp: '2026-09-07T00:00:00Z', value: 148200 }
      - { timestamp: '2026-09-14T00:00:00Z', value: 151900 }
      - { timestamp: '2026-09-21T00:00:00Z', value: 156300 }
      - { timestamp: '2026-09-28T00:00:00Z', value: 155940 }
    anomalies: []
    created_at: '2026-09-01T00:00:00Z'
    updated_at: '2026-09-29T11:00:00Z'
    last_event: reading_captured
    last_event_at: '2026-09-29T11:00:00Z'
  - usage_id: use_summit_inventory_2026_09
    subscription_id: sub_summit_business
    customer_name: Summit Outfitters
    meter_id: mtr_inventory_sync
    meter_name: Inventory sync
    provider: Stripe
    status: delayed
    trend_percent: -6.3
    included_quantity: 100000
    consumed_quantity: 48900
    currency: USD
    overage_rate_minor: 1
    variance_minor: 0
    projected_overage_minor: 0
    unit_label: API calls
    period_start: '2026-09-07'
    period_end: '2026-10-06'
    last_reported_at: '2026-09-27T06:00:00Z'
    samples:
      - { timestamp: '2026-09-10T00:00:00Z', value: 16100 }
      - { timestamp: '2026-09-17T00:00:00Z', value: 16800 }
      - { timestamp: '2026-09-24T00:00:00Z', value: 16000 }
    anomalies: []
    created_at: '2026-09-07T12:00:00Z'
    updated_at: '2026-09-27T06:00:00Z'
    last_event: reading_captured
    last_event_at: '2026-09-27T06:00:00Z'
  - usage_id: use_tidewater_search_2026_09
    subscription_id: sub_tidewater_enterprise
    customer_name: Tidewater Co-op
    meter_id: mtr_search_api
    meter_name: Search API
    provider: Stripe
    status: ok
    trend_percent: -2.4
    included_quantity: 500000
    consumed_quantity: 128400
    currency: USD
    overage_rate_minor: 1
    variance_minor: 0
    projected_overage_minor: 0
    unit_label: API calls
    period_start: '2026-09-01'
    period_end: '2026-09-30'
    last_reported_at: '2026-09-28T00:00:00Z'
    samples:
      - { timestamp: '2026-09-06T00:00:00Z', value: 42800 }
      - { timestamp: '2026-09-13T00:00:00Z', value: 43100 }
      - { timestamp: '2026-09-20T00:00:00Z', value: 42500 }
    anomalies: []
    created_at: '2026-09-01T00:00:00Z'
    updated_at: '2026-09-28T00:00:00Z'
    last_event: reset
    last_event_at: '2026-09-28T00:00:00Z'
```
