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

# Plan

Normalized plan definition capturing pricing, packaging, and entitlement metadata.

beta 3 traits · 7 contexts · 33 fields [Plan.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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

What `design_compose` reported for every screen here:

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

For this screen it also reported:

- `OODS-V122` Object "Plan" has a single trait category group for context "detail". Consider using a single-section layout instead of tabs.

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

3 calls, as the pipeline sent them

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

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

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

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

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

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

3 calls, as the pipeline sent them

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

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

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

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

The Vue app's content hash: `sha256:e37fbc985d9a594b78a2be09a841401871b2eb919fa845394654f95135d31afc`. 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 "Plan". Available contexts: list, card, detail

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

3 calls, as the pipeline sent them

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

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

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

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

The Vue app's content hash: `sha256:3abc0cc8512462814f988b22e4b48f7bf88e848cb760e4356dd524ab3be70f58`. 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 "Plan". Available contexts: list, card, detail

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

3 calls, as the pipeline sent them

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

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

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

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

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

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

3 calls, as the pipeline sent them

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

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

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

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

The Vue app's content hash: `sha256:0838fc45e1e2dfbff88234c982beafb4d9a476b5f5bb68a220e4a9b133304c3e`. 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 "Plan". Available contexts: list, card, detail

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

3 calls, as the pipeline sent them

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

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

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

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

The Vue app's content hash: `sha256:83c85edbcd89e418ad615d868be0e6006c9cca53d5a6b5b40ca892313d3e6401`. 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-V122` Object "Plan" has a single trait category group for context "detail". Consider using a single-section layout instead of tabs.
- `OODS-V119` No view_extensions found for context "form" in object "Plan". Available contexts: list, card, detail
- `OODS-V119` No view_extensions found for context "timeline" in object "Plan". Available contexts: list, card, detail

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

3 calls, as the pipeline sent them

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

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

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

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

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

## Fields

| Field | Type | Description |
| - | - | - |
| `plan_code` required | string | Provider specific identifier for the plan or price. |
| `plan_name` required | string | Human readable plan label rendered in list and detail contexts. |
| `billing_interval` required | string | Billing cadence name selected from supportedIntervals. |
| `interval_count` | integer | Multiplier for interval (ex: 12 with monthly => yearly cadence). |
| `amount_minor` required | integer | Contract value expressed in minor currency units. |
| `currency` required | string | ISO 4217 currency for the plan price. |
| `trial_period_days` | integer | Length of introductory trial period in days. |
| `collection_method` | string | How billing is collected (charge_automatically, send_invoice). |
| `billing_anchor_day` | integer | Day of month used to anchor renewals when prorating. |
| `pricing_model` | string | Price strategy (flat, per_unit, tiered, package). |
| `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. |
| `owner_id` required | string | Identifier of the owning principal scoped by owner_type. |
| `owner_type` required | string | Categorical owner type sourced from the ownerTypes parameter. |
| `ownership_role` | string | Optional role name describing how the owner governs the entity. |
| `ownership_transferred_at` | datetime | Timestamp recording when ownership was last transferred. |
| `plan_id` required | string | Stable identifier for the plan within the billing domain. |
| `product_family` required | string | High level product family grouping for analytics and reporting. |
| `status` required | string (active, deprecated, private_beta, legacy) | Availability state of the plan (active, deprecated, private_beta). |
| `feature_matrix` | FeatureDescriptor\[] | Array of feature descriptors listing entitlement tiers. |
| `add_on_ids` | string\[] | Identifiers for add-ons commonly sold with this plan. |
| `upgrade_targets` | string\[] | Plans presented as upgrade destinations. |
| `downgrade_targets` | string\[] | Plans that can be downgraded to from this plan. |
| `notes` | string | Internal commentary for packaging or finance teams. |
| `owner_name` | string | Display name of the team that owns the plan. |

## Traits

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

- [SaaSBillingBillable as Pricing](https://oods-foundry.com/traits/saas-billing-billable)
- [SaaSBillingMetered as IncludedUsage](https://oods-foundry.com/traits/saas-billing-metered)
- [Ownerable as PlanOwnership](https://oods-foundry.com/traits/ownerable)

## Relationships

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

- [Plan](https://oods-foundry.com/objects/plan), many-to-many, via `upgrade_targets`
- [Plan](https://oods-foundry.com/objects/plan), many-to-many, via `downgrade_targets`

## The object file

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

```
object:
  name: Plan
  version: 1.0.0
  domain: saas.billing
  description: Normalized plan definition capturing pricing, packaging, and entitlement metadata.
  tags:
    - billing
    - plan
    - packaging

traits:
  - name: SaaSBillingBillable
    alias: Pricing
  - name: SaaSBillingMetered
    alias: IncludedUsage
    parameters:
      unit: seats
      rolloverStrategy: none
      sampleWindowDays: 30
  - name: structural/Ownerable
    alias: PlanOwnership

schema:
  plan_id:
    type: string
    required: true
    description: Stable identifier for the plan within the billing domain.
  product_family:
    type: string
    required: true
    description: High level product family grouping for analytics and reporting.
  status:
    type: string
    required: true
    description: Availability state of the plan (active, deprecated, private_beta).
    validation:
      enum:
        - active
        - deprecated
        - private_beta
        - legacy
  feature_matrix:
    type: FeatureDescriptor[]
    required: false
    description: Array of feature descriptors listing entitlement tiers.
    default: []
  add_on_ids:
    type: string[]
    required: false
    description: Identifiers for add-ons commonly sold with this plan.
    default: []
  upgrade_targets:
    type: string[]
    required: false
    description: Plans presented as upgrade destinations.
    default: []
  downgrade_targets:
    type: string[]
    required: false
    description: Plans that can be downgraded to from this plan.
    default: []
  notes:
    type: string
    required: false
    description: Internal commentary for packaging or finance teams.
  owner_name:
    type: string
    required: false
    description: Display name of the team that owns the plan.

semantics:
  plan_id:
    semantic_type: billing.plan.id
    token_mapping: tokenMap(billing.plan.id)
  # The one-line summary under the plan's name in lists: the product family it belongs to.
  product_family:
    semantic_type: text.summary
    token_mapping: tokenMap(billing.plan.product_family)
  # structural/Ownerable's owner reference, named by owner_name.
  owner_id:
    semantic_type: ownership.owner.id
    token_mapping: tokenMap(ownership.owner.id)
    ui_hints:
      component: OwnerReference
      ownerTypeField: owner_type
      displayLabelField: owner_name
  status:
    semantic_type: billing.plan.status
    token_mapping: tokenMap(billing.plan.status)
  feature_matrix:
    semantic_type: billing.plan.feature_matrix
    token_mapping: tokenMap(billing.plan.feature_matrix)
  add_on_ids:
    semantic_type: billing.plan.add_on_ids
    token_mapping: tokenMap(billing.plan.add_on_ids)
  upgrade_targets:
    semantic_type: billing.plan.upgrade_targets
    token_mapping: tokenMap(billing.plan.upgrade_targets)
  downgrade_targets:
    semantic_type: billing.plan.downgrade_targets
    token_mapping: tokenMap(billing.plan.downgrade_targets)
  notes:
    semantic_type: billing.plan.notes
    token_mapping: tokenMap(billing.plan.notes)

tokens:
  billing.plan.id: "var(--cmp-text-strong)"
  billing.plan.status: "var(--cmp-badge-text-info)"
  billing.plan.product_family: "var(--cmp-text-subtle)"

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

# Authored type associations; no record join or referential-integrity claim.
relationships:
  - target: Plan
    via: upgrade_targets
    cardinality: many-to-many
    label: Upgrade destinations
  - target: Plan
    via: downgrade_targets
    cardinality: many-to-many
    label: Downgrade destinations

# Eight authored sample plans: the price book the sample subscriptions are on (their plan_code), plus a deprecated, a
# legacy and a private-beta plan. Prices are list prices in US dollars; the period is the price book the price belongs
# to, and each plan is owned by the team that prices it.
samples:
  - plan_id: plan_starter_monthly
    plan_code: starter-monthly
    plan_name: Starter
    product_family: Workspace plans
    status: active
    billing_interval: monthly
    interval_count: 1
    amount_minor: 1900
    currency: USD
    trial_period_days: 0
    collection_method: charge_automatically
    pricing_model: flat
    meter_name: Seats
    included_quantity: 3
    overage_rate_minor: 500
    period_start: '2026-01-01'
    period_end: '2026-12-31'
    upgrade_targets: [team-monthly]
    downgrade_targets: []
    add_on_ids: []
    owner_id: team_pricing
    owner_type: team
    owner_name: Pricing and packaging
    notes: Entry plan for single-location shops.
  - plan_id: plan_team_monthly
    plan_code: team-monthly
    plan_name: Team
    product_family: Workspace plans
    status: active
    billing_interval: monthly
    interval_count: 1
    amount_minor: 4900
    currency: USD
    trial_period_days: 14
    collection_method: charge_automatically
    pricing_model: flat
    meter_name: Seats
    included_quantity: 10
    overage_rate_minor: 500
    period_start: '2026-01-01'
    period_end: '2026-12-31'
    upgrade_targets: [business-monthly]
    downgrade_targets: [starter-monthly]
    add_on_ids: [analytics-addon-monthly]
    owner_id: team_pricing
    owner_type: team
    owner_name: Pricing and packaging
    notes: Most trials start here.
  - plan_id: plan_business_monthly
    plan_code: business-monthly
    plan_name: Business
    product_family: Workspace plans
    status: active
    billing_interval: monthly
    interval_count: 1
    amount_minor: 14900
    currency: USD
    trial_period_days: 14
    collection_method: charge_automatically
    pricing_model: flat
    meter_name: Seats
    included_quantity: 25
    overage_rate_minor: 400
    period_start: '2026-01-01'
    period_end: '2026-12-31'
    upgrade_targets: [enterprise-annual]
    downgrade_targets: [team-monthly]
    add_on_ids: [analytics-addon-monthly]
    owner_id: team_pricing
    owner_type: team
    owner_name: Pricing and packaging
    notes: Upgrades from Team are prorated and charged at once.
  - plan_id: plan_team_annual
    plan_code: team-annual
    plan_name: Team (annual)
    product_family: Workspace plans
    status: deprecated
    billing_interval: annual
    interval_count: 1
    amount_minor: 49000
    currency: USD
    trial_period_days: 14
    collection_method: charge_automatically
    pricing_model: flat
    meter_name: Seats
    included_quantity: 10
    overage_rate_minor: 500
    period_start: '2025-01-01'
    period_end: '2025-12-31'
    upgrade_targets: [business-monthly]
    downgrade_targets: [team-monthly]
    add_on_ids: []
    owner_id: team_pricing
    owner_type: team
    owner_name: Pricing and packaging
    notes: No longer sold; annual Team customers renew monthly from January 2026.
  - plan_id: plan_enterprise_annual
    plan_code: enterprise-annual
    plan_name: Enterprise
    product_family: Workspace plans
    status: active
    billing_interval: annual
    interval_count: 1
    amount_minor: 1200000
    currency: USD
    trial_period_days: 30
    collection_method: send_invoice
    pricing_model: flat
    meter_name: Seats
    included_quantity: 250
    overage_rate_minor: 300
    period_start: '2026-01-01'
    period_end: '2026-12-31'
    upgrade_targets: []
    downgrade_targets: [business-monthly]
    add_on_ids: [analytics-addon-monthly]
    owner_id: team_enterprise_sales
    owner_type: team
    owner_name: Enterprise sales
    notes: Invoiced yearly on net 30 terms; includes premium support.
  - plan_id: plan_analytics_addon_monthly
    plan_code: analytics-addon-monthly
    plan_name: Analytics add-on
    product_family: Add-ons
    status: active
    billing_interval: monthly
    interval_count: 1
    amount_minor: 3900
    currency: USD
    trial_period_days: 0
    collection_method: charge_automatically
    pricing_model: flat
    meter_name: Dashboards
    included_quantity: 20
    overage_rate_minor: 200
    period_start: '2026-01-01'
    period_end: '2026-12-31'
    upgrade_targets: []
    downgrade_targets: []
    add_on_ids: []
    owner_id: team_analytics
    owner_type: team
    owner_name: Analytics product
    notes: Sold with Team, Business and Enterprise.
  - plan_id: plan_pro_monthly_2025
    plan_code: pro-monthly
    plan_name: Pro
    product_family: Workspace plans
    status: legacy
    billing_interval: monthly
    interval_count: 1
    amount_minor: 9900
    currency: USD
    trial_period_days: 0
    collection_method: charge_automatically
    pricing_model: flat
    meter_name: Seats
    included_quantity: 15
    overage_rate_minor: 500
    period_start: '2025-01-01'
    period_end: '2025-12-31'
    upgrade_targets: [business-monthly]
    downgrade_targets: [team-monthly]
    add_on_ids: []
    owner_id: team_pricing
    owner_type: team
    owner_name: Pricing and packaging
    notes: Closed to new customers in October 2025; every Pro subscription moved to Business by April 2026.
  - plan_id: plan_business_plus_monthly
    plan_code: business-plus-monthly
    plan_name: Business Plus
    product_family: Workspace plans
    status: private_beta
    billing_interval: monthly
    interval_count: 1
    amount_minor: 24900
    currency: USD
    trial_period_days: 14
    collection_method: charge_automatically
    pricing_model: per_unit
    meter_name: Seats
    included_quantity: 50
    overage_rate_minor: 350
    period_start: '2026-09-01'
    period_end: '2026-12-31'
    upgrade_targets: [enterprise-annual]
    downgrade_targets: [business-monthly]
    add_on_ids: [analytics-addon-monthly]
    owner_id: team_pricing
    owner_type: team
    owner_name: Pricing and packaging
    notes: Invite-only beta for multi-location retailers.
```
