---
title: Subscription Terms
slug: subscription-terms
createdAt: 2026-03-17T21:13:53.446Z
---

# Subscription Terms

Subscription terms control the duration, billing cadence, renewal behavior, and date calculations for recurring products on a quote. This guide covers all common term configurations, from standard annual subscriptions to evergreen contracts and backdated quotes.

Use this guide when you need to configure subscription start and end dates, term lengths, billing periods, auto-renewal, or per-product term overrides.

## Term Calculation Rules

The pricing engine requires any two of the following three values to calculate the third:

| Provided                                        | Calculated              | Rule                                                       |
| ----------------------------------------------- | ----------------------- | ---------------------------------------------------------- |
| `subscriptionStartDate` + `subscriptionTerm`    | `subscriptionEndDate`   | End date = start date + term                               |
| `subscriptionStartDate` + `subscriptionEndDate` | `subscriptionTerm`      | Term = difference between dates in the specified dimension |
| `subscriptionEndDate` + `subscriptionTerm`      | `subscriptionStartDate` | Start date = end date - term                               |

If all three are provided, the engine uses the start date and term to verify the end date.

## Date Conventions

- All dates use ISO 8601 format: `YYYY-MM-DD` (e.g., `2025-01-01`).
- The `subscriptionTermDimension` field specifies the unit for the term value. Valid values: `"Month"`, `"Year"`, `"Day"`.
- When `subscriptionTermDimension` is `"Month"`, a `subscriptionTerm` of `12` equals one year.

## Billing Configuration Fields

| Field           | Type    | Valid Values                                            | Default                    | Description                                                            |
| --------------- | ------- | ------------------------------------------------------- | -------------------------- | ---------------------------------------------------------------------- |
| `billingPeriod` | string  | `"Monthly"`, `"Quarterly"`, `"Semi-Annual"`, `"Annual"` | Inherited from product     | How often the customer is invoiced                                     |
| `billingTiming` | string  | `"In Advance"`, `"In Arrears"`                          | Inherited from product     | Whether billing occurs at the start or end of each period              |
| `autoRenew`     | boolean | `true`, `false`                                         | `false`                    | Whether the subscription automatically renews at end of term           |
| `renewalTerm`   | number  | Any positive integer                                    | Same as `subscriptionTerm` | The term length for each renewal period                                |
| `evergreen`     | boolean | `true`, `false`                                         | `false`                    | Whether the subscription continues indefinitely with no fixed end date |

## Authentication Setup

All examples below use the following headers:

```javascript
const myHeaders = new Headers();
myHeaders.append("nue-api-key", "YOUR_API_KEY_HERE");
myHeaders.append("Content-Type", "application/json");
```

***

## Use Case 1: Standard 12-Month Term

The most common configuration: a 12-month subscription with explicit start date, end date, and term.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Standard Annual Subscription",
  subscriptionStartDate: "2025-01-01",
  subscriptionEndDate: "2026-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  products: [
    { productSku: "PLATFORM_BASE", uom: "User/Month", quantity: 50 }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  console.log(`Start: ${result.quote.subscriptionStartDate}`);
  console.log(`End: ${result.quote.subscriptionEndDate}`);
  console.log(`Term: ${result.quote.subscriptionTerm} months`);
  console.log(`Total: $${result.quote.totalAmount}`);
})
.catch(error => console.log('Error:', error));
```

```bash
curl -X POST 'https://api.nue.io/cpq/quotes:preview' \
  -H 'nue-api-key: YOUR_API_KEY_HERE' \
  -H 'Content-Type: application/json' \
  -d '{
    "opportunityId": "006xx000001abc123",
    "name": "Standard Annual Subscription",
    "subscriptionStartDate": "2025-01-01",
    "subscriptionEndDate": "2026-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "products": [
      { "productSku": "PLATFORM_BASE", "uom": "User/Month", "quantity": 50 }
    ]
  }'
```

The pricing engine calculates: `listUnitPrice * quantity * 12 months`.

***

## Use Case 2: 24-Month Term with Future Start Date

Create a subscription that starts 3 months in the future with a 24-month term. The end date is calculated automatically.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "24-Month Future Start",
  subscriptionStartDate: "2025-04-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 24,
  products: [
    { productSku: "PLATFORM_BASE", uom: "User/Month", quantity: 100 }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  console.log(`Start: ${result.quote.subscriptionStartDate}`);   // 2025-04-01
  console.log(`End: ${result.quote.subscriptionEndDate}`);       // 2027-04-01 (calculated)
  console.log(`Term: ${result.quote.subscriptionTerm} months`);  // 24
  console.log(`Total: $${result.quote.totalAmount}`);
})
.catch(error => console.log('Error:', error));
```

```bash
curl -X POST 'https://api.nue.io/cpq/quotes:preview' \
  -H 'nue-api-key: YOUR_API_KEY_HERE' \
  -H 'Content-Type: application/json' \
  -d '{
    "opportunityId": "006xx000001abc123",
    "name": "24-Month Future Start",
    "subscriptionStartDate": "2025-04-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 24,
    "products": [
      { "productSku": "PLATFORM_BASE", "uom": "User/Month", "quantity": 100 }
    ]
  }'
```

By providing only `subscriptionStartDate` and `subscriptionTerm`, the pricing engine calculates `subscriptionEndDate` as `2027-04-01`.

***

## Use Case 3: Short-Term Subscriptions (3 and 6 Months)

Create short-term subscriptions by specifying a lower `subscriptionTerm`. Multiple products can share the same term.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Short-Term 6-Month Trial",
  subscriptionStartDate: "2025-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 6,
  products: [
    { productSku: "PLATFORM_BASE", uom: "User/Month", quantity: 25 },
    { productSku: "ANALYTICS_ADDON", uom: "User/Month", quantity: 25 }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  console.log(`Term: ${result.quote.subscriptionTerm} months`);
  console.log(`End: ${result.quote.subscriptionEndDate}`);  // 2025-07-01 (calculated)
  console.log(`Total: $${result.quote.totalAmount}`);
  // Pricing reflects 6 months, not 12
})
.catch(error => console.log('Error:', error));
```

```bash
curl -X POST 'https://api.nue.io/cpq/quotes:preview' \
  -H 'nue-api-key: YOUR_API_KEY_HERE' \
  -H 'Content-Type: application/json' \
  -d '{
    "opportunityId": "006xx000001abc123",
    "name": "Short-Term 6-Month Trial",
    "subscriptionStartDate": "2025-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 6,
    "products": [
      { "productSku": "PLATFORM_BASE", "uom": "User/Month", "quantity": 25 },
      { "productSku": "ANALYTICS_ADDON", "uom": "User/Month", "quantity": 25 }
    ]
  }'
```

The total reflects 6 months of recurring charges rather than 12. The calculated end date is `2025-07-01`.

***

## Use Case 4: Per-Product Term Overrides

Different products on the same quote can have different subscription terms. Set `subscriptionTerm`, `subscriptionStartDate`, and `subscriptionEndDate` at the product level to override the quote-level values.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Mixed Term Lengths",
  subscriptionStartDate: "2025-01-01",
  subscriptionEndDate: "2026-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  products: [
    {
      productSku: "PLATFORM_BASE",
      uom: "User/Month",
      quantity: 50
      // Inherits quote-level: 12-month term, 2025-01-01 to 2026-01-01
    },
    {
      productSku: "ANALYTICS_ADDON",
      uom: "User/Month",
      quantity: 50,
      subscriptionTerm: 6,
      subscriptionStartDate: "2025-01-01",
      subscriptionEndDate: "2025-07-01"
      // Override: 6-month term for this product only
    },
    {
      productSku: "PREMIUM_SUPPORT",
      uom: "User/Month",
      quantity: 50,
      subscriptionTerm: 24,
      subscriptionStartDate: "2025-01-01",
      subscriptionEndDate: "2027-01-01"
      // Override: 24-month term for this product only
    }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  result.quoteLineItems.forEach(item => {
    console.log(`${item.product.sku}: term=${item.subscriptionTerm}mo, $${item.totalPrice}`);
  });
})
.catch(error => console.log('Error:', error));
```

```bash
curl -X POST 'https://api.nue.io/cpq/quotes:preview' \
  -H 'nue-api-key: YOUR_API_KEY_HERE' \
  -H 'Content-Type: application/json' \
  -d '{
    "opportunityId": "006xx000001abc123",
    "name": "Mixed Term Lengths",
    "subscriptionStartDate": "2025-01-01",
    "subscriptionEndDate": "2026-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "products": [
      { "productSku": "PLATFORM_BASE", "uom": "User/Month", "quantity": 50 },
      {
        "productSku": "ANALYTICS_ADDON",
        "uom": "User/Month",
        "quantity": 50,
        "subscriptionTerm": 6,
        "subscriptionStartDate": "2025-01-01",
        "subscriptionEndDate": "2025-07-01"
      },
      {
        "productSku": "PREMIUM_SUPPORT",
        "uom": "User/Month",
        "quantity": 50,
        "subscriptionTerm": 24,
        "subscriptionStartDate": "2025-01-01",
        "subscriptionEndDate": "2027-01-01"
      }
    ]
  }'
```

**Result:**

- `PLATFORM_BASE`: 12-month term (inherited from quote header).
- `ANALYTICS_ADDON`: 6-month term (product-level override).
- `PREMIUM_SUPPORT`: 24-month term (product-level override).

Each line item's `totalPrice` reflects its own term length.

***

## Use Case 5: Auto-Renew Configuration

Enable automatic renewal by setting `autoRenew: true` on the quote. Optionally specify a `renewalTerm` for the renewal period length. If `renewalTerm` is not provided, it defaults to the original `subscriptionTerm`.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Auto-Renewing Annual Subscription",
  subscriptionStartDate: "2025-01-01",
  subscriptionEndDate: "2026-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  autoRenew: true,
  renewalTerm: 12,
  products: [
    { productSku: "PLATFORM_BASE", uom: "User/Month", quantity: 50 },
    { productSku: "ANALYTICS_ADDON", uom: "User/Month", quantity: 25 }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  console.log(`Auto-renew: ${result.quote.autoRenew}`);              // true
  console.log(`Renewal term: ${result.quote.renewalTerm} months`);   // 12
  console.log(`Total (initial term): $${result.quote.totalAmount}`);
})
.catch(error => console.log('Error:', error));
```

```bash
curl -X POST 'https://api.nue.io/cpq/quotes:preview' \
  -H 'nue-api-key: YOUR_API_KEY_HERE' \
  -H 'Content-Type: application/json' \
  -d '{
    "opportunityId": "006xx000001abc123",
    "name": "Auto-Renewing Annual Subscription",
    "subscriptionStartDate": "2025-01-01",
    "subscriptionEndDate": "2026-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "autoRenew": true,
    "renewalTerm": 12,
    "products": [
      { "productSku": "PLATFORM_BASE", "uom": "User/Month", "quantity": 50 },
      { "productSku": "ANALYTICS_ADDON", "uom": "User/Month", "quantity": 25 }
    ]
  }'
```

The quote is priced for the initial 12-month term. The `autoRenew` and `renewalTerm` values are stored on the resulting subscription and control automatic renewal behavior at the end of the initial term.

***

## Use Case 6: Billing Period and Timing Overrides

Override the default billing period and timing at the quote level. These values apply to all products unless overridden at the product level.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Monthly In-Advance Billing",
  subscriptionStartDate: "2025-01-01",
  subscriptionEndDate: "2026-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  billingPeriod: "Monthly",
  billingTiming: "In Advance",
  products: [
    { productSku: "PLATFORM_BASE", uom: "User/Month", quantity: 50 },
    { productSku: "ANALYTICS_ADDON", uom: "User/Month", quantity: 25 }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  console.log(`Billing period: ${result.quote.billingPeriod}`);    // Monthly
  console.log(`Billing timing: ${result.quote.billingTiming}`);    // In Advance
  console.log(`Total: $${result.quote.totalAmount}`);
  result.quoteLineItems.forEach(item => {
    console.log(`${item.product.sku}: billingPeriod=${item.billingPeriod}, billingTiming=${item.billingTiming}`);
  });
})
.catch(error => console.log('Error:', error));
```

```bash
curl -X POST 'https://api.nue.io/cpq/quotes:preview' \
  -H 'nue-api-key: YOUR_API_KEY_HERE' \
  -H 'Content-Type: application/json' \
  -d '{
    "opportunityId": "006xx000001abc123",
    "name": "Monthly In-Advance Billing",
    "subscriptionStartDate": "2025-01-01",
    "subscriptionEndDate": "2026-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "billingPeriod": "Monthly",
    "billingTiming": "In Advance",
    "products": [
      { "productSku": "PLATFORM_BASE", "uom": "User/Month", "quantity": 50 },
      { "productSku": "ANALYTICS_ADDON", "uom": "User/Month", "quantity": 25 }
    ]
  }'
```

Both products inherit the quote-level `billingPeriod` and `billingTiming`. The total amount is the same regardless of billing period -- billing period affects invoice scheduling, not the quote total.

***

## Use Case 7: Evergreen Subscriptions

An evergreen subscription has no fixed end date. It continues indefinitely until explicitly canceled. Set `evergreen: true` on the quote. When evergreen is enabled, `subscriptionEndDate` and `subscriptionTerm` are not required.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Evergreen Subscription",
  subscriptionStartDate: "2025-01-01",
  subscriptionTermDimension: "Month",
  evergreen: true,
  billingPeriod: "Monthly",
  products: [
    { productSku: "PLATFORM_BASE", uom: "User/Month", quantity: 50 }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  console.log(`Evergreen: ${result.quote.evergreen}`);          // true
  console.log(`End date: ${result.quote.subscriptionEndDate}`); // null or not set
  console.log(`Total: $${result.quote.totalAmount}`);
  // Total is typically calculated for one billing period
})
.catch(error => console.log('Error:', error));
```

```bash
curl -X POST 'https://api.nue.io/cpq/quotes:preview' \
  -H 'nue-api-key: YOUR_API_KEY_HERE' \
  -H 'Content-Type: application/json' \
  -d '{
    "opportunityId": "006xx000001abc123",
    "name": "Evergreen Subscription",
    "subscriptionStartDate": "2025-01-01",
    "subscriptionTermDimension": "Month",
    "evergreen": true,
    "billingPeriod": "Monthly",
    "products": [
      { "productSku": "PLATFORM_BASE", "uom": "User/Month", "quantity": 50 }
    ]
  }'
```

:::BlockQuote
**Note:** Evergreen subscriptions conflict with `autoRenew`. Do not set both `evergreen: true` and `autoRenew: true` -- an evergreen subscription has no term boundary to trigger renewal.
:::

***

## Use Case 8: Term Calculation from Dates

Provide only `subscriptionStartDate` and `subscriptionEndDate` and let the pricing engine calculate the term automatically. This is useful when the business requirement is defined by calendar dates rather than a fixed number of months.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Date-Driven Term Calculation",
  subscriptionStartDate: "2025-03-15",
  subscriptionEndDate: "2026-09-15",
  subscriptionTermDimension: "Month",
  products: [
    { productSku: "PLATFORM_BASE", uom: "User/Month", quantity: 50 }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  console.log(`Start: ${result.quote.subscriptionStartDate}`);              // 2025-03-15
  console.log(`End: ${result.quote.subscriptionEndDate}`);                  // 2026-09-15
  console.log(`Calculated term: ${result.quote.subscriptionTerm} months`);  // 18
  console.log(`Total: $${result.quote.totalAmount}`);
})
.catch(error => console.log('Error:', error));
```

```bash
curl -X POST 'https://api.nue.io/cpq/quotes:preview' \
  -H 'nue-api-key: YOUR_API_KEY_HERE' \
  -H 'Content-Type: application/json' \
  -d '{
    "opportunityId": "006xx000001abc123",
    "name": "Date-Driven Term Calculation",
    "subscriptionStartDate": "2025-03-15",
    "subscriptionEndDate": "2026-09-15",
    "subscriptionTermDimension": "Month",
    "products": [
      { "productSku": "PLATFORM_BASE", "uom": "User/Month", "quantity": 50 }
    ]
  }'
```

The pricing engine calculates the term as 18 months (from March 15, 2025 to September 15, 2026) and prices accordingly.

***

## Use Case 9: Backdated Quotes

Create a quote with a start date in the past. This is useful for retroactive contracts or late-entry deals. The pricing engine calculates the term and total based on the provided dates regardless of the current calendar date.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Backdated Quote",
  subscriptionStartDate: "2024-10-01",
  subscriptionEndDate: "2025-10-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  products: [
    { productSku: "PLATFORM_BASE", uom: "User/Month", quantity: 50 }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  console.log(`Start: ${result.quote.subscriptionStartDate}`);  // 2024-10-01 (in the past)
  console.log(`End: ${result.quote.subscriptionEndDate}`);      // 2025-10-01
  console.log(`Term: ${result.quote.subscriptionTerm} months`); // 12
  console.log(`Total: $${result.quote.totalAmount}`);
})
.catch(error => console.log('Error:', error));
```

```bash
curl -X POST 'https://api.nue.io/cpq/quotes:preview' \
  -H 'nue-api-key: YOUR_API_KEY_HERE' \
  -H 'Content-Type: application/json' \
  -d '{
    "opportunityId": "006xx000001abc123",
    "name": "Backdated Quote",
    "subscriptionStartDate": "2024-10-01",
    "subscriptionEndDate": "2025-10-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "products": [
      { "productSku": "PLATFORM_BASE", "uom": "User/Month", "quantity": 50 }
    ]
  }'
```

The pricing engine does not reject past start dates. The full 12-month term is priced normally. Downstream billing and invoicing systems handle proration or catch-up invoices for the elapsed period.

## Term and Billing Field Reference

| Field                       | Type              | Scope               | Description                                                                |
| --------------------------- | ----------------- | ------------------- | -------------------------------------------------------------------------- |
| `subscriptionStartDate`     | string (ISO date) | Quote root, Product | Start date of the subscription                                             |
| `subscriptionEndDate`       | string (ISO date) | Quote root, Product | End date of the subscription                                               |
| `subscriptionTerm`          | number            | Quote root, Product | Duration of the subscription in the specified dimension                    |
| `subscriptionTermDimension` | string            | Quote root          | Unit for the term: `"Month"`, `"Year"`, or `"Day"`                         |
| `billingPeriod`             | string            | Quote root, Product | Invoice frequency: `"Monthly"`, `"Quarterly"`, `"Semi-Annual"`, `"Annual"` |
| `billingTiming`             | string            | Quote root, Product | When to bill: `"In Advance"` or `"In Arrears"`                             |
| `autoRenew`                 | boolean           | Quote root          | Whether the subscription auto-renews                                       |
| `renewalTerm`               | number            | Quote root          | Term length for renewals (defaults to `subscriptionTerm`)                  |
| `evergreen`                 | boolean           | Quote root          | Whether the subscription is open-ended with no fixed end date              |

## Key Behaviors Summary

| Scenario                              | What Happens                                                  |
| ------------------------------------- | ------------------------------------------------------------- |
| Start + term provided, no end date    | End date is calculated automatically                          |
| Start + end date provided, no term    | Term is calculated automatically                              |
| All three provided                    | Start + term used; end date verified                          |
| Product-level term override           | Product uses its own dates/term instead of quote header       |
| `autoRenew: true`                     | Subscription renews at end of term for `renewalTerm` months   |
| `evergreen: true`                     | No end date; subscription continues until canceled            |
| `evergreen: true` + `autoRenew: true` | Conflict -- do not combine; evergreen has no renewal boundary |
| Backdated start date                  | Accepted; pricing calculated normally from the past date      |
| `billingPeriod` / `billingTiming`     | Affects invoice scheduling, not the quote total amount        |

## Next Steps

- **[Discounts](docId\:Y9AwhgT5IYIBlYMwVE6nX)** -- Apply header, parent, and line-level discretionary discounts
- **[Price Tags](docId\:Z5zOtt7ESzhMHAXIFqMKr)** -- Apply tiered, volume, and ramp pricing adjustments
- **[Bundles](docId\:fri8QGGG2M1jVPi-Qlnvi)** -- Work with bundle products and add-ons
- **[Create Quote Overview](docId\:BC-IdxYnwAUS7O9EFYCwq)** -- Return to the full API reference
