> ## Documentation Index
> Fetch the complete documentation index at: https://guide.withvayu.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Product Structure

> How to define products in contracts

Products are the line items inside a contract. Each product defines what is being charged, how it is scheduled, and what pricing model applies.

## Base fields

| Field               | Type    | Required | Description                                                       |
| ------------------- | ------- | -------- | ----------------------------------------------------------------- |
| `displayName`       | string  | Yes      | Label shown on invoices                                           |
| `scheduling`        | object  | Yes      | When and how often the product bills                              |
| `pricing`           | object  | Yes      | The pricing model                                                 |
| `catalogProductId`  | string  | No       | Links to a catalog product — required for all usage-based pricing |
| `description`       | string  | No       | Internal description                                              |
| `paymentTerm`       | string  | No       | `prepayment` or `postpayment` — defaults based on pricing type    |
| `isCalendarAligned` | boolean | No       | Align invoice periods to calendar months (default: `false`)       |
| `commitment`        | object  | No       | Minimum committed units — see [Commitment](#commitment)           |
| `productErpId`      | string  | No       | ERP identifier for accounting sync                                |

## Scheduling

```json theme={null}
{
  "scheduling": {
    "billingDay": 1,
    "duration": { "unit": "MONTH", "value": 1 }
  }
}
```

| Field            | Type             | Description                                                                                                       |
| ---------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------- |
| `billingDay`     | integer (1–31)   | Day of month the billing period starts. Defaults to `1`. Should match the contract start date to avoid proration. |
| `duration.unit`  | string           | `DAY`, `WEEK`, `MONTH`, or `YEAR`                                                                                 |
| `duration.value` | integer (0–1000) | Number of units per billing period                                                                                |

## Pricing models

### ONE\_TIME

A single charge billed when the contract starts. Duration must be 1 day.

```json theme={null}
{
  "pricing": {
    "type": "ONE_TIME",
    "price": 500.00
  }
}
```

### SUBSCRIPTION

Recurring fixed fee. The `subscriptionCadence` controls how often the charge accumulates within the billing period.

```json theme={null}
{
  "pricing": {
    "type": "SUBSCRIPTION",
    "price": 99.00,
    "subscriptionCadence": { "unit": "MONTH", "value": 1 }
  }
}
```

A product with a 3-month `duration` and monthly `subscriptionCadence` bills 3× $99 = $297 per invoice.

### CONTRACT\_TERMS

A total contract fee, optionally split into installments at specific dates.

```json theme={null}
{
  "pricing": {
    "type": "CONTRACT_TERMS",
    "price": 12000.00,
    "installments": [
      { "installmentDate": "2026-01-01T00:00:00Z", "amount": 6000.00 },
      { "installmentDate": "2026-07-01T00:00:00Z", "amount": 6000.00 }
    ]
  }
}
```

### PER\_UNIT

Pay-as-you-go. Requires `catalogProductId`.

```json theme={null}
{
  "pricing": {
    "type": "PER_UNIT",
    "price": 0.002,
    "chunkSize": 1000,
    "baseAmount": 500,
    "usageReset": 1
  }
}
```

| Field        | Type   | Description                                                                  |
| ------------ | ------ | ---------------------------------------------------------------------------- |
| `price`      | number | Price per unit (or per chunk if `chunkSize` is set)                          |
| `chunkSize`  | number | Billing granularity — usage is rounded up to the nearest chunk               |
| `baseAmount` | number | Free units included before metered charges begin                             |
| `usageReset` | number | Reset accumulated usage every N months — must be `1`, `2`, `3`, `6`, or `12` |

### TIERED

Volume-based pricing with different rates or flat fees per tier. Requires `catalogProductId`.

```json theme={null}
{
  "pricing": {
    "type": "TIERED",
    "tiers": [
      { "fromInclusive": 0, "toExclusive": 1000, "rate": 0.10 },
      { "fromInclusive": 1000, "toExclusive": 10000, "rate": 0.07 },
      { "fromInclusive": 10000, "rate": 0.04 }
    ],
    "subscriptionCadence": { "unit": "MONTH", "value": 1 },
    "autoUpgrade": false,
    "prorate": false,
    "baseAmount": 0,
    "usageReset": 1
  }
}
```

| Tier field      | Type           | Description                                                           |
| --------------- | -------------- | --------------------------------------------------------------------- |
| `fromInclusive` | number         | Lower bound of the tier (inclusive)                                   |
| `toExclusive`   | number \| null | Upper bound (exclusive). Omit or `null` for the final open-ended tier |
| `rate`          | number         | Per-unit rate in this tier                                            |
| `flatFee`       | number         | Flat fee charged when usage enters this tier                          |
| `packageSize`   | number         | Units grouped into a package for billing                              |

| Tiered option         | Type    | Description                                                              |
| --------------------- | ------- | ------------------------------------------------------------------------ |
| `subscriptionCadence` | object  | Makes tiered pricing subscription-based (charges flat fees on a cadence) |
| `autoUpgrade`         | boolean | Automatically move to the next tier in the following billing period      |
| `prorate`             | boolean | Prorate flat fees based on when the tier was entered mid-period          |
| `isRevShare`          | boolean | Revenue share mode — `rate` is treated as a percentage                   |
| `baseAmount`          | number  | Free units before tiered charges apply                                   |
| `usageReset`          | number  | Reset usage every N months: `1`, `2`, `3`, `6`, or `12`                  |

## Commitment

Attach a minimum committed usage to any usage-based product.

```json theme={null}
{
  "commitment": {
    "units": 10000,
    "price": 500.00,
    "overageStrategy": "IGNORE"
  }
}
```

| Field             | Type   | Description                                                         |
| ----------------- | ------ | ------------------------------------------------------------------- |
| `units`           | number | Committed usage units                                               |
| `price`           | number | Price charged for the committed amount                              |
| `overageStrategy` | string | What happens when usage exceeds the commitment — `IGNORE` (default) |
| `scheduling`      | object | For recurring commitments — same shape as product scheduling        |

## Product groups

Products can be grouped to share ERP settings, commitments, and a combined line item on invoices.

```json theme={null}
{
  "productGroups": [
    {
      "displayName": "Platform Bundle",
      "products": [
        {
          "displayName": "Base Subscription",
          "scheduling": { "billingDay": 1, "duration": { "unit": "MONTH", "value": 1 } },
          "pricing": { "type": "SUBSCRIPTION", "price": 500.00, "subscriptionCadence": { "unit": "MONTH", "value": 1 } }
        },
        {
          "displayName": "API Usage",
          "scheduling": { "billingDay": 1, "duration": { "unit": "MONTH", "value": 1 } },
          "pricing": { "type": "PER_UNIT", "price": 0.001, "chunkSize": 100 },
          "catalogProductId": "cat_abc123"
        }
      ]
    }
  ]
}
```

<Note>
  Products inside a `productGroup` cannot use `isCalendarAligned`. Group-level settings like `commitment` and ERP fields apply to all products in the group.
</Note>
