---
title: Bundles Advanced
slug: bundles-advanced
createdAt: 2026-03-17T21:13:54.077Z
---

# Bundles Advanced

This guide covers advanced bundle scenarios for the Nue CPQ Quote API, including dynamic product options, per-addon overrides, nested bundles, quantity scaling, and multi-bundle quotes. For basic bundle usage (auto-populated children, optional add-ons, simple quantities), see [Bundles](docId\:fri8QGGG2M1jVPi-Qlnvi).

Use this guide when you need to accept or reject specific add-ons, override billing or term settings on individual add-ons, work with bundles inside bundles, or understand how quantity scaling behaves across bundle hierarchies.

## Quantity Scaling Modes

When a bundle parent has a quantity greater than 1, child add-on quantities can scale in different ways depending on the product configuration:

| Mode                     | Behavior                                                      | Example (parent qty = 5, child configured qty = 2) |
| ------------------------ | ------------------------------------------------------------- | -------------------------------------------------- |
| **LinkToBundleQuantity** | Child quantity = parent quantity \* child configured quantity | Child qty = 5 \* 2 = 10                            |
| **Independent**          | Child quantity is independent of the parent                   | Child qty = 2 (unchanged)                          |

The quantity mode is configured in the product catalog on each add-on's relationship to its parent. It cannot be changed at quote time.

## Auto-Renew on Nested Bundles

When `autoRenew: true` is set on the quote header, it applies to all products including nested bundle hierarchies. Each subscription created from the quote -- parent and children alike -- inherits the auto-renew setting.

## 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: Dynamic Product Options (Accepted and Rejected Add-Ons)

Control which optional add-ons are included on a bundle by listing only the desired add-ons in the `addOns` array. Add-ons not listed are excluded from the quote. Bundled (required) add-ons are always auto-populated regardless of the `addOns` array contents.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Selective Add-Ons",
  subscriptionStartDate: "2025-01-01",
  subscriptionEndDate: "2026-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  products: [
    {
      productSku: "ENTERPRISE_SUITE",
      uom: "User/Month",
      quantity: 50,
      addOns: [
        // Accept PREMIUM_SUPPORT and DATA_EXPORT
        { productSku: "PREMIUM_SUPPORT", uom: "User/Month", quantity: 50 },
        { productSku: "DATA_EXPORT", uom: "User/Month", quantity: 50 }
        // ADVANCED_ANALYTICS and COMPLIANCE_MODULE are optional but not listed -- they are excluded
      ]
    }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  const parent = result.quoteLineItems[0];
  console.log(`Parent: ${parent.product.sku}`);
  console.log(`Children: ${parent.childrenLineItems.length}`);
  parent.childrenLineItems.forEach(child => {
    console.log(`  └─ ${child.product.sku}: qty=${child.quantity}, $${child.totalPrice}`);
  });
  // Includes: auto-populated bundled items + PREMIUM_SUPPORT + DATA_EXPORT
  // Excludes: ADVANCED_ANALYTICS, COMPLIANCE_MODULE (not in addOns)
})
.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": "Selective Add-Ons",
    "subscriptionStartDate": "2025-01-01",
    "subscriptionEndDate": "2026-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "products": [
      {
        "productSku": "ENTERPRISE_SUITE",
        "uom": "User/Month",
        "quantity": 50,
        "addOns": [
          { "productSku": "PREMIUM_SUPPORT", "uom": "User/Month", "quantity": 50 },
          { "productSku": "DATA_EXPORT", "uom": "User/Month", "quantity": 50 }
        ]
      }
    ]
  }'
```

The response `childrenLineItems` contains only the auto-populated bundled items plus the two explicitly accepted add-ons. Optional add-ons not listed in `addOns` are not included.

***

## Use Case 2: Per-Add-On Overrides (Term, Billing Period, Billing Timing)

Individual add-ons within a bundle can have their own `subscriptionTerm`, `billingPeriod`, and `billingTiming` values that differ from the parent bundle and from each other.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Per-AddOn Overrides",
  subscriptionStartDate: "2025-01-01",
  subscriptionEndDate: "2026-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  billingPeriod: "Annual",
  billingTiming: "In Advance",
  products: [
    {
      productSku: "ENTERPRISE_SUITE",
      uom: "User/Month",
      quantity: 50,
      addOns: [
        {
          productSku: "PREMIUM_SUPPORT",
          uom: "User/Month",
          quantity: 50,
          billingPeriod: "Monthly",
          billingTiming: "In Arrears"
          // Override: billed monthly in arrears instead of annual in advance
        },
        {
          productSku: "DATA_EXPORT",
          uom: "User/Month",
          quantity: 50,
          subscriptionTerm: 6,
          subscriptionStartDate: "2025-01-01",
          subscriptionEndDate: "2025-07-01",
          billingPeriod: "Quarterly",
          billingTiming: "In Advance"
          // Override: 6-month term, quarterly billing
        }
      ]
    }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  const parent = result.quoteLineItems[0];
  console.log(`Parent billing: ${parent.billingPeriod}, ${parent.billingTiming}`);
  parent.childrenLineItems.forEach(child => {
    console.log(`  └─ ${child.product.sku}: term=${child.subscriptionTerm}mo, billing=${child.billingPeriod} ${child.billingTiming}, $${child.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": "Per-AddOn Overrides",
    "subscriptionStartDate": "2025-01-01",
    "subscriptionEndDate": "2026-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "billingPeriod": "Annual",
    "billingTiming": "In Advance",
    "products": [
      {
        "productSku": "ENTERPRISE_SUITE",
        "uom": "User/Month",
        "quantity": 50,
        "addOns": [
          {
            "productSku": "PREMIUM_SUPPORT",
            "uom": "User/Month",
            "quantity": 50,
            "billingPeriod": "Monthly",
            "billingTiming": "In Arrears"
          },
          {
            "productSku": "DATA_EXPORT",
            "uom": "User/Month",
            "quantity": 50,
            "subscriptionTerm": 6,
            "subscriptionStartDate": "2025-01-01",
            "subscriptionEndDate": "2025-07-01",
            "billingPeriod": "Quarterly",
            "billingTiming": "In Advance"
          }
        ]
      }
    ]
  }'
```

**Result:**

- `ENTERPRISE_SUITE` parent: 12-month term, Annual In Advance billing.
- `PREMIUM_SUPPORT`: inherits the 12-month term, but uses Monthly In Arrears billing.
- `DATA_EXPORT`: 6-month term override, Quarterly In Advance billing.

***

## Use Case 3: Nested Bundles (Bundle Within a Bundle)

A bundle can contain another bundle as a child. The inner bundle's own children (auto-populated and explicit add-ons) are resolved recursively. In the response, the nested bundle appears inside the outer bundle's `childrenLineItems`, and the nested bundle has its own `childrenLineItems` for its children.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Nested Bundle Quote",
  subscriptionStartDate: "2025-01-01",
  subscriptionEndDate: "2026-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  products: [
    {
      productSku: "ENTERPRISE_SUITE",
      uom: "User/Month",
      quantity: 10,
      addOns: [
        {
          productSku: "ANALYTICS_BUNDLE",   // This is itself a bundle
          uom: "User/Month",
          quantity: 10,
          addOns: [
            { productSku: "ADVANCED_DASHBOARDS", uom: "User/Month", quantity: 10 }
          ]
        },
        { productSku: "PREMIUM_SUPPORT", uom: "User/Month", quantity: 10 }
      ]
    }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  const outer = result.quoteLineItems[0];
  console.log(`Outer bundle: ${outer.product.sku}`);

  outer.childrenLineItems.forEach(child => {
    console.log(`  └─ ${child.product.sku}: $${child.totalPrice}`);
    if (child.childrenLineItems && child.childrenLineItems.length > 0) {
      child.childrenLineItems.forEach(grandchild => {
        console.log(`      └─ ${grandchild.product.sku}: $${grandchild.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": "Nested Bundle Quote",
    "subscriptionStartDate": "2025-01-01",
    "subscriptionEndDate": "2026-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "products": [
      {
        "productSku": "ENTERPRISE_SUITE",
        "uom": "User/Month",
        "quantity": 10,
        "addOns": [
          {
            "productSku": "ANALYTICS_BUNDLE",
            "uom": "User/Month",
            "quantity": 10,
            "addOns": [
              { "productSku": "ADVANCED_DASHBOARDS", "uom": "User/Month", "quantity": 10 }
            ]
          },
          { "productSku": "PREMIUM_SUPPORT", "uom": "User/Month", "quantity": 10 }
        ]
      }
    ]
  }'
```

**Response structure:**

```javascript
ENTERPRISE_SUITE (outer bundle)
  └─ ANALYTICS_BUNDLE (inner bundle)
      └─ [auto-populated bundled children of ANALYTICS_BUNDLE]
      └─ ADVANCED_DASHBOARDS (explicit add-on of inner bundle)
  └─ PREMIUM_SUPPORT (add-on of outer bundle)
  └─ [auto-populated bundled children of ENTERPRISE_SUITE]
```

The inner bundle's `childrenLineItems` array contains its own resolved children, creating a multi-level hierarchy.

***

## Use Case 4: Multi-Level Explicit Add-On Configuration

Configure explicit add-ons at multiple levels of a nested bundle hierarchy. Each level's `addOns` array controls which optional products are included at that level.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Multi-Level Add-On Config",
  subscriptionStartDate: "2025-01-01",
  subscriptionEndDate: "2026-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  products: [
    {
      productSku: "ENTERPRISE_SUITE",
      uom: "User/Month",
      quantity: 20,
      discount: 10,
      addOns: [
        {
          productSku: "ANALYTICS_BUNDLE",
          uom: "User/Month",
          quantity: 20,
          discount: 15,
          addOns: [
            { productSku: "ADVANCED_DASHBOARDS", uom: "User/Month", quantity: 20 },
            { productSku: "REAL_TIME_STREAMING", uom: "User/Month", quantity: 20 }
          ]
        },
        { productSku: "PREMIUM_SUPPORT", uom: "User/Month", quantity: 20 },
        { productSku: "DATA_EXPORT", uom: "User/Month", quantity: 20 }
      ]
    }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  const outer = result.quoteLineItems[0];
  console.log(`${outer.product.sku}: ${outer.discount}% off`);

  outer.childrenLineItems.forEach(child => {
    console.log(`  └─ ${child.product.sku}: ${child.discount}% off, $${child.totalPrice}`);
    if (child.childrenLineItems && child.childrenLineItems.length > 0) {
      child.childrenLineItems.forEach(gc => {
        console.log(`      └─ ${gc.product.sku}: ${gc.discount}% off, $${gc.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": "Multi-Level Add-On Config",
    "subscriptionStartDate": "2025-01-01",
    "subscriptionEndDate": "2026-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "products": [
      {
        "productSku": "ENTERPRISE_SUITE",
        "uom": "User/Month",
        "quantity": 20,
        "discount": 10,
        "addOns": [
          {
            "productSku": "ANALYTICS_BUNDLE",
            "uom": "User/Month",
            "quantity": 20,
            "discount": 15,
            "addOns": [
              { "productSku": "ADVANCED_DASHBOARDS", "uom": "User/Month", "quantity": 20 },
              { "productSku": "REAL_TIME_STREAMING", "uom": "User/Month", "quantity": 20 }
            ]
          },
          { "productSku": "PREMIUM_SUPPORT", "uom": "User/Month", "quantity": 20 },
          { "productSku": "DATA_EXPORT", "uom": "User/Month", "quantity": 20 }
        ]
      }
    ]
  }'
```

**Discount propagation:**

- `ENTERPRISE_SUITE` has 10% off. Its direct children (`PREMIUM_SUPPORT`, `DATA_EXPORT`) inherit 10%.
- `ANALYTICS_BUNDLE` has its own 15% off (overrides parent's 10%). Its children (`ADVANCED_DASHBOARDS`, `REAL_TIME_STREAMING`) inherit 15%.

***

## Use Case 5: Large Bundle Quantity (LinkToBundleQuantity Scaling)

When the parent bundle quantity is large, child add-ons configured with `LinkToBundleQuantity` scale their quantities proportionally. This example uses a parent quantity of 5 to demonstrate the scaling behavior.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Large Bundle Quantity Scaling",
  subscriptionStartDate: "2025-01-01",
  subscriptionEndDate: "2026-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  products: [
    {
      productSku: "ENTERPRISE_SUITE",
      uom: "User/Month",
      quantity: 5,
      addOns: [
        { productSku: "PREMIUM_SUPPORT", uom: "User/Month", quantity: 1 },
        { productSku: "DATA_EXPORT", uom: "User/Month", quantity: 2 }
      ]
    }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  const parent = result.quoteLineItems[0];
  console.log(`Parent: ${parent.product.sku}, qty=${parent.quantity}`);

  parent.childrenLineItems.forEach(child => {
    console.log(`  └─ ${child.product.sku}: qty=${child.quantity}, $${child.totalPrice}`);
    // If LinkToBundleQuantity:
    //   PREMIUM_SUPPORT: 5 * 1 = 5
    //   DATA_EXPORT: 5 * 2 = 10
    // If Independent:
    //   PREMIUM_SUPPORT: 1
    //   DATA_EXPORT: 2
  });
})
.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": "Large Bundle Quantity Scaling",
    "subscriptionStartDate": "2025-01-01",
    "subscriptionEndDate": "2026-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "products": [
      {
        "productSku": "ENTERPRISE_SUITE",
        "uom": "User/Month",
        "quantity": 5,
        "addOns": [
          { "productSku": "PREMIUM_SUPPORT", "uom": "User/Month", "quantity": 1 },
          { "productSku": "DATA_EXPORT", "uom": "User/Month", "quantity": 2 }
        ]
      }
    ]
  }'
```

**Result with LinkToBundleQuantity mode:**

- `PREMIUM_SUPPORT`: resolved quantity = 5 \* 1 = 5.
- `DATA_EXPORT`: resolved quantity = 5 \* 2 = 10.

**Result with Independent mode:**

- `PREMIUM_SUPPORT`: resolved quantity = 1 (as specified).
- `DATA_EXPORT`: resolved quantity = 2 (as specified).

The actual scaling behavior depends on how the add-on relationship is configured in the product catalog. Check the response `quantity` field on each child line item to confirm the resolved quantity.

***

## Use Case 6: Two Bundles and a Standalone in the Same Quote

A quote can contain multiple bundles and standalone products. Each bundle is resolved independently, and all products are priced together on the same quote.

```javascript
const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Multi-Bundle + Standalone",
  subscriptionStartDate: "2025-01-01",
  subscriptionEndDate: "2026-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  discount: 5,
  products: [
    {
      productSku: "ENTERPRISE_SUITE",
      uom: "User/Month",
      quantity: 25,
      discount: 10,
      addOns: [
        { productSku: "PREMIUM_SUPPORT", uom: "User/Month", quantity: 25 },
        { productSku: "DATA_EXPORT", uom: "User/Month", quantity: 25 }
      ]
    },
    {
      productSku: "ANALYTICS_BUNDLE",
      uom: "User/Month",
      quantity: 15,
      addOns: [
        { productSku: "ADVANCED_DASHBOARDS", uom: "User/Month", quantity: 15 }
      ]
    },
    { productSku: "NUE_ON_SALESFORCE", uom: "User/Month", quantity: 10 }
  ]
};

fetch('https://api.nue.io/cpq/quotes:preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  console.log(`Total: $${result.quote.totalAmount}`);
  console.log(`Top-level items: ${result.quoteLineItems.length}`);  // 3

  result.quoteLineItems.forEach(item => {
    const children = item.childrenLineItems || [];
    if (children.length > 0) {
      console.log(`Bundle: ${item.product.sku} (${item.discount}% off, ${children.length} children)`);
      children.forEach(child => {
        console.log(`  └─ ${child.product.sku}: qty=${child.quantity}, $${child.totalPrice}`);
      });
    } else {
      console.log(`Standalone: ${item.product.sku}: ${item.discount}% off, $${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": "Multi-Bundle + Standalone",
    "subscriptionStartDate": "2025-01-01",
    "subscriptionEndDate": "2026-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "discount": 5,
    "products": [
      {
        "productSku": "ENTERPRISE_SUITE",
        "uom": "User/Month",
        "quantity": 25,
        "discount": 10,
        "addOns": [
          { "productSku": "PREMIUM_SUPPORT", "uom": "User/Month", "quantity": 25 },
          { "productSku": "DATA_EXPORT", "uom": "User/Month", "quantity": 25 }
        ]
      },
      {
        "productSku": "ANALYTICS_BUNDLE",
        "uom": "User/Month",
        "quantity": 15,
        "addOns": [
          { "productSku": "ADVANCED_DASHBOARDS", "uom": "User/Month", "quantity": 15 }
        ]
      },
      { "productSku": "NUE_ON_SALESFORCE", "uom": "User/Month", "quantity": 10 }
    ]
  }'
```

**Result:**

- `ENTERPRISE_SUITE` bundle: 10% product-level discount (overrides the 5% header discount). Its children inherit 10%.
- `ANALYTICS_BUNDLE` bundle: no product-level discount, so it receives the 5% header discount. Its children inherit 5%.
- `NUE_ON_SALESFORCE` standalone: no product-level discount, so it receives the 5% header discount.

The quote `totalAmount` is the sum of all line items across both bundles and the standalone product.

## Response Structure for Nested Bundles

Nested bundles produce a multi-level `childrenLineItems` hierarchy:

```json
{
  "quote": {
    "totalAmount": 12345.00
  },
  "quoteLineItems": [
    {
      "product": { "sku": "ENTERPRISE_SUITE" },
      "quantity": 10,
      "totalPrice": 8000.00,
      "childrenLineItems": [
        {
          "product": { "sku": "ANALYTICS_BUNDLE" },
          "quantity": 10,
          "totalPrice": 3000.00,
          "childrenLineItems": [
            {
              "product": { "sku": "ADVANCED_DASHBOARDS" },
              "quantity": 10,
              "totalPrice": 1200.00,
              "childrenLineItems": []
            }
          ]
        },
        {
          "product": { "sku": "PREMIUM_SUPPORT" },
          "quantity": 10,
          "totalPrice": 500.00,
          "childrenLineItems": []
        }
      ]
    }
  ]
}
```

Key points:

- Each level of nesting adds another `childrenLineItems` array.
- Leaf products (non-bundles) have an empty `childrenLineItems` array.
- The parent's `totalPrice` reflects the combined pricing of the entire bundle hierarchy as configured in the catalog.

## Summary

| Scenario                       | What to Specify                                                                | Key Behavior                                          |
| ------------------------------ | ------------------------------------------------------------------------------ | ----------------------------------------------------- |
| Accept/reject optional add-ons | List desired add-ons in `addOns`                                               | Unlisted optional add-ons are excluded                |
| Per-addon billing overrides    | Set `billingPeriod`, `billingTiming`, `subscriptionTerm` on individual add-ons | Overrides apply to that add-on only                   |
| Nested bundles                 | Add a bundle SKU inside another bundle's `addOns` with its own `addOns`        | Resolved recursively; multi-level `childrenLineItems` |
| Multi-level discounts          | Set `discount` on each bundle level                                            | Each level's discount propagates to its own children  |
| LinkToBundleQuantity scaling   | Set parent quantity; child quantities multiply                                 | Depends on catalog configuration                      |
| Multiple bundles in one quote  | List each bundle in `products` array                                           | Each resolved independently                           |

## Next Steps

- **[Bundles](docId\:fri8QGGG2M1jVPi-Qlnvi)** -- Basic bundle usage and fundamentals
- **[Discounts](docId\:Y9AwhgT5IYIBlYMwVE6nX)** -- Apply header, parent, and line-level discretionary discounts
- **[Subscription Terms](docId\:Wwo0BZASGS6MDCUE_G_Kl)** -- Configure term lengths, billing periods, and renewal settings
- **[Create Quote Overview](docId\:BC-IdxYnwAUS7O9EFYCwq)** -- Return to the full API reference
