---
title: Preview vs Commit
slug: preview-vs-commit
createdAt: 2026-03-17T21:13:54.379Z
---

# Preview vs Commit

The Nue CPQ Quote API offers two modes for creating quotes: **preview** (dry-run) and **commit** (persist). Both modes execute the full pricing engine -- product resolution, bundle expansion, discount propagation, and price tag evaluation -- but differ in whether the result is saved to the database. This guide explains when to use each mode, shows how the request and response differ, and demonstrates the common preview-then-commit pattern.

## Overview Comparison

| Aspect                       | Preview                          | Commit                       |
| ---------------------------- | -------------------------------- | ---------------------------- |
| **Endpoint**                 | `POST /cpq/quotes:preview`       | `POST /cpq/quotes`           |
| **Pricing Calculation**      | Full pricing engine              | Full pricing engine          |
| **Database Writes**          | None                             | Quote + line items persisted |
| **Response&#x20;**`quote.id` | absent                           | Real ID                      |
| **Request Body**             | Identical                        | Identical                    |
| **Use Case**                 | Validation, what-if, UI previews | Creating finalized quotes    |

## Authentication

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: Preview Mode -- Pricing Preview

Preview a quote to see calculated pricing without creating any database records. This is ideal for pricing previews in a UI, what-if analysis, AI-driven validation, and integration testing.

**Request Body:**

```json
{
  "opportunityId": "006xx000001abc123",
  "name": "Q1 2026 Enterprise License",
  "subscriptionStartDate": "2026-01-01",
  "subscriptionEndDate": "2027-01-01",
  "subscriptionTermDimension": "Month",
  "subscriptionTerm": 12,
  "products": [
    { "productSku": "NUE_ON_SALESFORCE", "uom": "User/Month", "quantity": 10 }
  ]
}
```

**curl:**

```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": "Q1 2026 Enterprise License",
    "subscriptionStartDate": "2026-01-01",
    "subscriptionEndDate": "2027-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "products": [
      { "productSku": "NUE_ON_SALESFORCE", "uom": "User/Month", "quantity": 10 }
    ]
  }'
```

**JavaScript fetch:**

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

const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Q1 2026 Enterprise License",
  subscriptionStartDate: "2026-01-01",
  subscriptionEndDate: "2027-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  products: [
    { 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('Preview result:');
  console.log(`  quote.id: ${result.quote.id}`);         // undefined -- not persisted
  console.log(`  Total Amount: $${result.quote.totalAmount}`);
  console.log(`  Line items: ${result.quoteLineItems.length}`);
})
.catch(error => console.log('Error:', error));
```

**Expected Response:**

```json
{
  "quote": {
    "name": "Q1 2026 Enterprise License",
    "totalAmount": 3588.00,
    "subscriptionStartDate": "2026-01-01",
    "subscriptionEndDate": "2027-01-01",
    "subscriptionTerm": 12,
    "subscriptionTermDimension": "Month"
  },
  "quoteLineItems": [
    {
      "product": { "sku": "NUE_ON_SALESFORCE", "name": "Nue on Salesforce" },
      "quantity": 10,
      "listPrice": 29.90,
      "listTotalPrice": 3588.00,
      "totalPrice": 3588.00,
      "childrenLineItems": []
    }
  ]
}
```

The `quote` object has no `id` because nothing was written to the database.

***

## Use Case 2: Commit Mode -- Create a Real Quote

Commit the quote to persist it to the database. The request body is identical to preview; only the endpoint changes.

**Request Body:**

```json
{
  "opportunityId": "006xx000001abc123",
  "name": "Q1 2026 Enterprise License",
  "subscriptionStartDate": "2026-01-01",
  "subscriptionEndDate": "2027-01-01",
  "subscriptionTermDimension": "Month",
  "subscriptionTerm": 12,
  "products": [
    { "productSku": "NUE_ON_SALESFORCE", "uom": "User/Month", "quantity": 10 }
  ]
}
```

**curl:**

```bash
curl -X POST 'https://api.nue.io/cpq/quotes' \
  -H 'nue-api-key: YOUR_API_KEY_HERE' \
  -H 'Content-Type: application/json' \
  -d '{
    "opportunityId": "006xx000001abc123",
    "name": "Q1 2026 Enterprise License",
    "subscriptionStartDate": "2026-01-01",
    "subscriptionEndDate": "2027-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "products": [
      { "productSku": "NUE_ON_SALESFORCE", "uom": "User/Month", "quantity": 10 }
    ]
  }'
```

**JavaScript fetch:**

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

const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Q1 2026 Enterprise License",
  subscriptionStartDate: "2026-01-01",
  subscriptionEndDate: "2027-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  products: [
    { productSku: "NUE_ON_SALESFORCE", uom: "User/Month", quantity: 10 }
  ]
};

fetch('https://api.nue.io/cpq/quotes', {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify(quoteData)
})
.then(response => response.json())
.then(result => {
  console.log('Commit result:');
  console.log(`  quote.id: ${result.quote.id}`);           // UUID -- persisted
  console.log(`  Total Amount: $${result.quote.totalAmount}`);
  console.log(`  Line items: ${result.quoteLineItems.length}`);
})
.catch(error => console.log('Error:', error));
```

**Expected Response:**

```json
{
  "quote": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "Q1 2026 Enterprise License",
    "totalAmount": 3588.00,
    "subscriptionStartDate": "2026-01-01",
    "subscriptionEndDate": "2027-01-01",
    "subscriptionTerm": 12,
    "subscriptionTermDimension": "Month"
  },
  "quoteLineItems": [
    {
      "product": { "sku": "NUE_ON_SALESFORCE", "name": "Nue on Salesforce" },
      "quantity": 10,
      "listPrice": 29.90,
      "listTotalPrice": 3588.00,
      "totalPrice": 3588.00,
      "childrenLineItems": []
    }
  ]
}
```

The `quote.id` now contains a UUID. The quote, line items, and all pricing data are persisted.

***

## Use Case 3: Preview-Then-Commit Pattern

A common integration pattern is to preview a quote first, present the pricing to a user or validation system, and then commit only after approval. Because the request body is the same for both endpoints, you can reuse the exact same payload.

**Request Body (used for both calls):**

```json
{
  "opportunityId": "006xx000001abc123",
  "name": "Q1 2026 Enterprise License",
  "subscriptionStartDate": "2026-01-01",
  "subscriptionEndDate": "2027-01-01",
  "subscriptionTermDimension": "Month",
  "subscriptionTerm": 12,
  "discount": 10,
  "products": [
    { "productSku": "NUE_ON_SALESFORCE", "uom": "User/Month", "quantity": 10 },
    { "productSku": "NUE_PLATFORM", "uom": "User/Year", "quantity": 5 }
  ]
}
```

**curl:**

```bash
# Step 1: Preview
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": "Q1 2026 Enterprise License",
    "subscriptionStartDate": "2026-01-01",
    "subscriptionEndDate": "2027-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "discount": 10,
    "products": [
      { "productSku": "NUE_ON_SALESFORCE", "uom": "User/Month", "quantity": 10 },
      { "productSku": "NUE_PLATFORM", "uom": "User/Year", "quantity": 5 }
    ]
  }'

# Step 2: If approved, commit with the same body
curl -X POST 'https://api.nue.io/cpq/quotes' \
  -H 'nue-api-key: YOUR_API_KEY_HERE' \
  -H 'Content-Type: application/json' \
  -d '{
    "opportunityId": "006xx000001abc123",
    "name": "Q1 2026 Enterprise License",
    "subscriptionStartDate": "2026-01-01",
    "subscriptionEndDate": "2027-01-01",
    "subscriptionTermDimension": "Month",
    "subscriptionTerm": 12,
    "discount": 10,
    "products": [
      { "productSku": "NUE_ON_SALESFORCE", "uom": "User/Month", "quantity": 10 },
      { "productSku": "NUE_PLATFORM", "uom": "User/Year", "quantity": 5 }
    ]
  }'
```

**JavaScript fetch:**

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

const quoteData = {
  opportunityId: "006xx000001abc123",
  name: "Q1 2026 Enterprise License",
  subscriptionStartDate: "2026-01-01",
  subscriptionEndDate: "2027-01-01",
  subscriptionTermDimension: "Month",
  subscriptionTerm: 12,
  discount: 10,
  products: [
    { productSku: "NUE_ON_SALESFORCE", uom: "User/Month", quantity: 10 },
    { productSku: "NUE_PLATFORM", uom: "User/Year", quantity: 5 }
  ]
};

async function previewThenCommit(quotePayload) {
  // Step 1: Preview the quote
  const previewResponse = await fetch('https://api.nue.io/cpq/quotes:preview', {
    method: 'POST',
    headers: myHeaders,
    body: JSON.stringify(quotePayload)
  });
  const preview = await previewResponse.json();

  console.log('--- Preview ---');
  console.log(`  quote.id: ${preview.quote.id}`);             // undefined
  console.log(`  Total Amount: $${preview.quote.totalAmount}`);
  console.log(`  Line items: ${preview.quoteLineItems.length}`);

  // Step 2: Validate or present to user
  const totalAmount = preview.quote.totalAmount;
  if (totalAmount > 50000) {
    console.log('Quote exceeds $50,000 -- requires manager approval.');
    return preview;
  }

  // Step 3: Commit the same payload
  const commitResponse = await fetch('https://api.nue.io/cpq/quotes', {
    method: 'POST',
    headers: myHeaders,
    body: JSON.stringify(quotePayload)
  });
  const committed = await commitResponse.json();

  console.log('--- Committed ---');
  console.log(`  quote.id: ${committed.quote.id}`);            // UUID
  console.log(`  Total Amount: $${committed.quote.totalAmount}`);

  return committed;
}

previewThenCommit(quoteData)
  .then(result => console.log('Done.'))
  .catch(error => console.log('Error:', error));
```

**Expected Preview Response:**

```json
{
  "quote": {
    "name": "Q1 2026 Enterprise License",
    "totalAmount": 3674.70,
    "discount": 10
  },
  "quoteLineItems": [
    {
      "product": { "sku": "NUE_ON_SALESFORCE", "name": "Nue on Salesforce" },
      "quantity": 10,
      "listTotalPrice": 3588.00,
      "discount": 10,
      "totalPrice": 3229.20
    },
    {
      "product": { "sku": "NUE_PLATFORM", "name": "Nue Platform" },
      "quantity": 5,
      "listTotalPrice": 495.00,
      "discount": 10,
      "totalPrice": 445.50
    }
  ]
}
```

**Expected Commit Response:**

```json
{
  "quote": {
    "id": "f7e8d9c0-b1a2-3456-cdef-789012345678",
    "name": "Q1 2026 Enterprise License",
    "totalAmount": 3674.70,
    "discount": 10
  },
  "quoteLineItems": [
    {
      "product": { "sku": "NUE_ON_SALESFORCE", "name": "Nue on Salesforce" },
      "quantity": 10,
      "listTotalPrice": 3588.00,
      "discount": 10,
      "totalPrice": 3229.20
    },
    {
      "product": { "sku": "NUE_PLATFORM", "name": "Nue Platform" },
      "quantity": 5,
      "listTotalPrice": 495.00,
      "discount": 10,
      "totalPrice": 445.50
    }
  ]
}
```

The only difference between the two responses is the `quote.id` field.

***

## Behavior Comparison

| Behavior               | Preview                            | Commit                               |
| ---------------------- | ---------------------------------- | ------------------------------------ |
| Product resolution     | Full                               | Full                                 |
| Bundle expansion       | Full                               | Full                                 |
| Pricing engine         | Full calculation                   | Full calculation                     |
| Discount propagation   | Full                               | Full                                 |
| Price tag evaluation   | Full                               | Full                                 |
| Database writes        | None                               | Quote + all line items persisted     |
| `quote.id` in response | absent                             | present                              |
| Idempotency            | Fully idempotent (no side effects) | Creates a new quote each call        |
| Downstream triggers    | None                               | May trigger workflows, notifications |

## When to Use Each Mode

| Scenario                  | Mode                       | Why                                                  |
| ------------------------- | -------------------------- | ---------------------------------------------------- |
| Price calculator UI       | Preview                    | No database clutter from exploratory pricing         |
| AI agent building a quote | Preview first, then Commit | Validate pricing before persisting                   |
| Batch quote generation    | Commit                     | Directly persist finalized quotes                    |
| What-if comparisons       | Preview                    | Run multiple scenarios without side effects          |
| Integration testing       | Preview                    | Validate API integration without creating records    |
| Final quote creation      | Commit                     | Persist the approved quote for downstream processing |

## Key Takeaways

1. The request body is identical for both endpoints -- only the URL differs.
2. Preview runs the full pricing engine but does not persist anything.
3. Commit runs the same pricing engine and saves the result to the database.
4. Use the preview-then-commit pattern to validate before persisting.
5. In preview mode the `quote` object has no `id`, and line items carry `temp_<uuid>` ids. In commit mode both carry real ids.
