---
title: Invoice Preview
slug: invoice-preview
docTags: 
createdAt: 2026-04-14T01:06:02.683Z
---

This guide covers the Invoice Preview endpoint (`POST /orders/invoice-preview`), which computes invoice data for both initial orders and change orders without persisting any data. Use it to show customers what they will be billed before committing to an order.

## Prerequisites

Before you begin, ensure you have:

- A valid Nue API key with order permissions
- For initial order previews: a customer ID and price book entry IDs
- For change order previews: asset numbers (SUB-XXXXXX format) for existing subscriptions
- Basic knowledge of REST APIs and JSON

:::hint{type="info"}
**Single Endpoint, Two Modes**

The invoice preview endpoint handles both initial orders and change orders through a single `POST /orders/invoice-preview` call. The request body determines which mode is used:

- Include `orderProducts` for an **initial order** preview
- Include `assetChanges` for a **change order** preview

You cannot include both in the same request.
:::

## Authentication

All invoice preview requests require authentication using your Nue API key in the `nue-api-key` header:

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

## Key Behaviors

| Behavior                  | Details                                                                                                                                                                         |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Zero persistence**      | The endpoint computes invoices entirely in-memory. No orders, subscriptions, or invoices are written to the database.                                                           |
| **Initial order preview** | Provide `orderProducts` to preview invoices for a new order. Uses the same pricing engine as `POST /orders`.                                                                    |
| **Change order preview**  | Provide `assetChanges` to preview invoices for modifications to existing subscriptions. Uses the same pricing engine as `POST /change-orders`.                                  |
| **Mutual exclusivity**    | Exactly one of `orderProducts` or `assetChanges` must be present. Sending both returns a validation error.                                                                      |
| **Tax**                   | Tax calculation is not supported on invoice previews. To obtain tax amounts, create a draft order via `POST /orders` instead.                                                   |
| **Forbidden options**     | The options `generateInvoice`, `activateInvoice`, and `asyncPayment` are rejected with an error if set to `true`. These are execution-time flags that do not apply to previews. |

***

## Initial Order Invoice Preview

Preview invoices for a new order by providing `orderProducts`. The request body accepts the same product fields as `POST /orders` (see [Create Draft Orders](docId\:ikvnHfXqfd1R5zoTi-u7Y)).

### Basic Example

Preview the invoice for a single product subscription:

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

const previewRequest = {
  customer: {
    id: "d2e04653-ae90-49df-a986-134cf64f6d03"
  },
  effectiveDate: "2025-07-01",
  orderProducts: [
    {
      priceBookEntryId: "01uQL000009Tsn7YAC",
      quantity: 10,
      subscriptionStartDate: "2025-07-01",
      subscriptionTerm: 12
    }
  ]
};

fetch('https://api.nue.io/orders/invoice-preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(previewRequest)
})
.then(response => response.json())
.then(result => {
  console.log('Invoice preview:', result);

  if (result.previewInvoices && result.previewInvoices.length > 0) {
    const invoice = result.previewInvoices[0];
    console.log(`Invoice Amount: $${invoice.amount}`);
    console.log(`Start Date: ${invoice.startDate}`);
    console.log(`End Date: ${invoice.endDate}`);

    // Iterate invoice line items
    invoice.items.forEach(item => {
      console.log(`  ${item.productName}: $${item.amount}`);
    });
  }
})
.catch(error => console.log('Error:', error));
```

### Multiple Products

Preview invoices for multiple products:

```javascript
const previewRequest = {
  customer: {
    id: "d2e04653-ae90-49df-a986-134cf64f6d03"
  },
  effectiveDate: "2025-07-01",
  orderProducts: [
    {
      priceBookEntryId: "01uQL000009Tsn7YAC",
      quantity: 10,
      subscriptionStartDate: "2025-07-01",
      subscriptionTerm: 12
    },
    {
      priceBookEntryId: "01uQL000009Tsn8YAC",
      quantity: 5,
      subscriptionStartDate: "2025-07-01",
      subscriptionTerm: 12
    }
  ]
};

fetch('https://api.nue.io/orders/invoice-preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(previewRequest)
})
.then(response => response.json())
.then(result => {
  if (result.previewInvoices) {
    result.previewInvoices.forEach(invoice => {
      console.log(`Amount: $${invoice.amount}`);
      console.log(`Start: ${invoice.startDate}`);
      console.log(`End: ${invoice.endDate}`);
    });
  }
})
.catch(error => console.log('Error:', error));
```

### Bundle Products

Bundles work the same as in `POST /orders` — specify add-ons for optional bundle components:

```javascript
const previewRequest = {
  customer: {
    id: "d2e04653-ae90-49df-a986-134cf64f6d03"
  },
  effectiveDate: "2025-07-01",
  orderProducts: [
    {
      priceBookEntryId: "01uQL000009BundleABC",
      quantity: 10,
      subscriptionStartDate: "2025-07-01",
      subscriptionTerm: 12,
      addOns: [
        {
          productOptionId: "opt_IMPL_SERVICE",
          productOptionQuantity: 20
        }
      ]
    }
  ]
};

fetch('https://api.nue.io/orders/invoice-preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(previewRequest)
})
.then(response => response.json())
.then(result => {
  console.log('Bundle invoice preview:', result.previewInvoices);
})
.catch(error => console.log('Error:', error));
```

***

## Change Order Invoice Preview

Preview invoices for changes to existing subscriptions by providing `assetChanges`. The request body accepts the same change fields as `POST /change-orders` (see [Creating Draft Change Orders](docId\:zsXM12TfKlA93EQZgiGm9)).

### Quantity Update

Preview the billing impact of adding seats to an existing subscription:

```javascript
const previewRequest = {
  assetChanges: [
    {
      changeType: "UpdateQuantity",
      assetNumber: "SUB-00003725",
      quantity: 25,
      startDate: "2025-07-15"
    }
  ]
};

fetch('https://api.nue.io/orders/invoice-preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(previewRequest)
})
.then(response => response.json())
.then(result => {
  if (result.previews && result.previews.length > 0) {
    const preview = result.previews[0];
    console.log(`Asset: ${preview.assetNumber}`);

    const summary = preview.priceSummary;
    console.log(`Today's Charge: $${summary.todayChargePrice}`);
    console.log(`Next Billing Period: $${summary.nextBillingPeriodPrice}`);
    console.log(`Next Billing Date: ${summary.nextBillingDate}`);

    const asset = preview.previewResult;
    console.log(`New Quantity: ${asset.quantity}`);
    console.log(`Start Date: ${asset.startDate}`);
    console.log(`End Date: ${asset.endDate}`);
  }
})
.catch(error => console.log('Error:', error));
```

### Renewal

Preview the invoice for renewing a subscription:

```javascript
const previewRequest = {
  assetChanges: [
    {
      changeType: "Renew",
      assetNumber: "SUB-00003725",
      renewalTerm: 12
    }
  ]
};

fetch('https://api.nue.io/orders/invoice-preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(previewRequest)
})
.then(response => response.json())
.then(result => {
  if (result.previews) {
    const preview = result.previews[0];
    console.log(`Total Price: $${preview.priceSummary.totalPrice}`);
    console.log(`New End Date: ${preview.previewResult.endDate}`);
  }
})
.catch(error => console.log('Error:', error));
```

### Upgrade

Preview the cost of upgrading to a higher-tier product:

```javascript
const previewRequest = {
  assetChanges: [
    {
      changeType: "Upgrade",
      assetNumber: "SUB-00003725",
      targetPriceBookEntryId: "01uEm00000CNoaXIAT",
      startDate: "2025-07-15"
    }
  ]
};

fetch('https://api.nue.io/orders/invoice-preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(previewRequest)
})
.then(response => response.json())
.then(result => {
  if (result.previews) {
    const preview = result.previews[0];
    console.log(`Today's Charge: $${preview.priceSummary.todayChargePrice}`);
    console.log(`Next Period: $${preview.priceSummary.nextBillingPeriodPrice}`);
  }
})
.catch(error => console.log('Error:', error));
```

### Cancellation

Preview any remaining charges or credits for cancelling a subscription:

```javascript
const previewRequest = {
  assetChanges: [
    {
      changeType: "Cancel",
      assetNumber: "SUB-00003725",
      cancellationDate: "2025-08-01"
    }
  ]
};

fetch('https://api.nue.io/orders/invoice-preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(previewRequest)
})
.then(response => response.json())
.then(result => {
  if (result.previews) {
    const preview = result.previews[0];
    console.log(`Cancellation Date: ${preview.previewResult.cancellationDate}`);
    console.log(`Today's Charge: $${preview.priceSummary.todayChargePrice}`);
  }
})
.catch(error => console.log('Error:', error));
```

### Cross-Sell (New Products on Change Order)

Add new products alongside changes to existing subscriptions. The `products` array requires at least one accompanying entry in `assetChanges`:

```javascript
const previewRequest = {
  assetChanges: [
    {
      changeType: "Renew",
      assetNumber: "SUB-00003725",
      renewalTerm: 12
    }
  ],
  products: [
    {
      priceBookEntryId: "01uQL000009Tsn8YAC",
      quantity: 5,
      subscriptionStartDate: "2025-07-01",
      subscriptionTerm: 12
    }
  ]
};

fetch('https://api.nue.io/orders/invoice-preview', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(previewRequest)
})
.then(response => response.json())
.then(result => {
  console.log('Change order + cross-sell preview:', result.previews);
})
.catch(error => console.log('Error:', error));
```

***

## Request Reference

### Top-Level Fields

| Field              | Type   | Required            | Description                                                                         |
| ------------------ | ------ | ------------------- | ----------------------------------------------------------------------------------- |
| `customer`         | object | Yes (initial order) | Customer placing the order. Must contain an `id` field.                             |
| `effectiveDate`    | string | No                  | Effective date in `YYYY-MM-DD` format. Used for initial order previews.             |
| `orderProducts`    | array  | Yes (initial order) | Product lines for an initial order preview. Same schema as `POST /orders`.          |
| `assetChanges`     | array  | Yes (change order)  | Asset changes for a change order preview. Same schema as `POST /change-orders`.     |
| `products`         | array  | No                  | New products to add alongside a change order (cross-sell). Requires `assetChanges`. |
| `billingPeriod`    | string | No                  | Billing period for the order.                                                       |
| `billingAccountId` | string | No                  | Billing account ID.                                                                 |
| `description`      | string | No                  | Order description.                                                                  |
| `customFields`     | object | No                  | Custom fields for the order.                                                        |
| `timeZone`         | string | No                  | Time zone for date calculations (change orders).                                    |
| `poNumber`         | string | No                  | Purchase order number.                                                              |
| `poDate`           | string | No                  | Purchase order date in `YYYY-MM-DD` format.                                         |

:::hint{type="warning"}
**Forbidden Options**

The following options are rejected with an error if set to `true`: `generateInvoice`, `activateInvoice`, `asyncPayment`. These are execution-time flags that do not apply to previews.
:::

### Validation Rules

| Rule                                                | Error                              |
| --------------------------------------------------- | ---------------------------------- |
| Both `orderProducts` and `assetChanges` provided    | `INVOICE_PREVIEW_INVALID_PAYLOAD`  |
| Both `orderProducts` and `products` provided        | `INVOICE_PREVIEW_INVALID_PAYLOAD`  |
| `products` provided without `assetChanges`          | `CHANGE_TYPE_COMBINATION_REQUIRED` |
| Neither `orderProducts` nor `assetChanges` provided | `INVOICE_PREVIEW_MISSING_BODY`     |

***

## Response Reference

The response shape depends on whether you submitted an initial order or change order preview.

### Initial Order Response

For `orderProducts` requests, the response contains `previewInvoices`:

| Field                                | Type   | Description                                         |
| ------------------------------------ | ------ | --------------------------------------------------- |
| `previewInvoices`                    | array  | List of computed invoice objects.                   |
| `previewInvoices[].amount`           | number | Total invoice amount.                               |
| `previewInvoices[].amountWithoutTax` | number | Invoice subtotal amount.                            |
| `previewInvoices[].invoiceDate`      | string | Invoice date.                                       |
| `previewInvoices[].dueDate`          | string | Payment due date.                                   |
| `previewInvoices[].startDate`        | string | Billing period start date.                          |
| `previewInvoices[].endDate`          | string | Billing period end date.                            |
| `previewInvoices[].currencyIsoCode`  | string | ISO currency code.                                  |
| `previewInvoices[].items`            | array  | Invoice line items with per-product billing detail. |

### Change Order Response

For `assetChanges` requests, the response contains `previews`:

| Field                       | Type   | Description                                         |
| --------------------------- | ------ | --------------------------------------------------- |
| `previews`                  | array  | List of per-asset preview objects.                  |
| `previews[].assetNumber`    | string | The subscription asset number.                      |
| `previews[].priceSummary`   | object | Aggregated billing summary (see below).             |
| `previews[].previewResult`  | object | Updated asset state after the change (see below).   |
| `previews[].previewRequest` | object | Echo of the original change request for this asset. |

### Price Summary

| Field                     | Type   | Description                                              |
| ------------------------- | ------ | -------------------------------------------------------- |
| `totalPrice`              | number | Total price across all billing periods.                  |
| `totalAmount`             | number | Total amount across all periods.                         |
| `todayChargePrice`        | number | Immediate charge price (prorated for mid-cycle changes). |
| `todayChargeAmount`       | number | Immediate charge amount.                                 |
| `nextBillingPeriodPrice`  | number | Price for the next full billing period.                  |
| `nextBillingPeriodAmount` | number | Amount for the next billing period.                      |
| `nextBillingDate`         | string | Date of the next billing cycle.                          |

### Preview Result

| Field              | Type   | Description                                        |
| ------------------ | ------ | -------------------------------------------------- |
| `assetNumber`      | string | Subscription asset number.                         |
| `quantity`         | number | Quantity after the change.                         |
| `term`             | number | Term after the change.                             |
| `startDate`        | string | Subscription start date.                           |
| `endDate`          | string | Subscription end date after the change.            |
| `cancellationDate` | string | Cancellation effective date (Cancel changes only). |
| `orderPrice`       | object | Order-level pricing detail.                        |
| `billingPrice`     | object | Billing-level pricing detail.                      |
| `changes`          | array  | Itemized list of changes applied.                  |
| `childrenAssets`   | array  | Child asset previews for bundle subscriptions.     |
