# Update a quote

Operation ID: `updateQuote`

Group: CRM › Quotes

[Open in the interactive reference](https://docs.api.lensing.ai/lensing/v1/endpoints/updateQuote)

`PATCH /crm/quotes/{id}`

Retry-safe: A write that accepts Idempotency-Key: repeating a request with the same key replays the stored answer instead of executing twice.

Updates a quote. Every field is optional and an omitted one stays as it is. The quote's children are changed through create, update and delete arrays: createSubscriptions, updateSubscriptions and deleteSubscriptions for subscriptions, createNonRecurringProducts, updateNonRecurringProducts and deleteNonRecurringProducts for the products outside a subscription, and the same three arrays one level down for the products of a subscription (createQuoteProducts ...) and the lines of a product (createQuoteProductLines ...). Items in an update array are matched by their id from GET crm/quotes/:id; deleting a subscription or product removes everything under it. A line's lineTiers and invoiceMilestones are replaced wholesale when sent and kept when omitted, as the sales order update endpoint does with tiers. Its rateCardEntries are matched as the sales order endpoint matches them: an entry with an id updates that entry, one without is added, and a current entry left out is deleted. A changed line's pricing is reconciled as the sales order endpoints reconcile it: unitPrice wins over discountAmount, which wins over discountPercentage, the other two are derived against the line's listPrice, and a listPrice sent alone keeps the line's discount amount (tiered, volume, stairstep and rateCard lines excepted). discountPercentage is sent on a 0-100 scale, as the sales order endpoints take it, and stored and returned as a 0-1 fraction. On a 'changeOrder' quote the addresses are those derived at creation and cannot be changed (QUOTE_TYPE_MISMATCH). The quote is validated as a whole afterward, as the quote page validates it, and a failure of those rules returns VALIDATION_FAILED naming the rule. A quote that is under signing, signed or completed cannot be changed (QUOTE_LOCKED). Changing a quote whose approval process has started sends it back to approval, as an edit on the quote page does. The quote type, opportunity and sales arrangement cannot be changed. The response is empty.

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Api-Version` | header | string · v1 | yes | The API version this request targets, named by its public identifier. Required on every request; omitting it, or naming a version this company does not have, is answered with 400. This document describes version `v1`. |
| `Idempotency-Key` | header | string | no | An opaque caller-chosen string (1-255 characters) that makes this request safe to retry. Repeating the same key with an identical request body replays the original response instead of re-executing - but only once that original request succeeded; a failed attempt re-executes on retry. Repeating the key with a different body is answered with 422. A key still in flight is answered with 409 - as is a key whose original request was interrupted before it finished, for a few minutes afterwards, until that attempt is presumed dead. A completed response stays replayable for 24 hours. The key is scoped to the caller, not to the action: reusing it for a different action is answered with 409 or 422 rather than treated independently. On read actions this header is ignored. On write actions that cannot offer the guarantee it is answered with `400 IDEMPOTENCY_NOT_SUPPORTED` rather than silently ignored. |
| `id` | path | string | yes | The identifier of the quote to change. Example: `"3b7d5e9c-1a24-4f80-9c6d-2e8f70b13a45"`. |

## Request body

Required, `application/json`: updateQuoteInput.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `quoteDate` | date | no | The date the quote is drawn up. Format YYYY-MM-DD. Omit to leave unchanged. |
| `serviceStartDate` | date | no | The first date products or services on this quote are delivered. Format YYYY-MM-DD. Omit to leave unchanged. |
| `paymentTerm` | string | no | The code of the payment term. See code on GET accounting/payment-terms. Omit to leave unchanged. |
| `billToAddressId` | string | no | The address to bill; the quote's own copy is overwritten with it. Not accepted on a 'changeOrder' quote. Omit to leave unchanged. |
| `soldToAddressId` | string | no | The address the products are sold to; the quote's own copy is overwritten with it. Not accepted on a 'changeOrder' quote. Omit to leave unchanged. |
| `isPrimary` | boolean | no | Pass true to make this the opportunity's primary quote. A primary quote cannot be unset; make another quote primary instead. Omit to leave unchanged. |
| `memo` | string | no | A free-text memo for the quote. Omit to leave unchanged. Example: `"Renegotiated after the pilot."`. |
| `signDate` | date | no | The date the quote was signed. Format YYYY-MM-DD. Omit to leave unchanged. |
| `oneTimeDiscountAmount` | decimal | no | A one-time discount on the whole quote, in the quote's currency. Omit to leave unchanged. |
| `oneTimeDiscountAllocation` | any | no | How oneTimeDiscountAmount is spread across the quote's invoices. Omit to leave unchanged. One of: `"firstInvoice"`, `"alignToInvoiceFrequency"`, `"custom"`. |
| `billableTimeCappedPrice` | decimal | no | The ceiling on the total of the quote's billable-time lines, in the quote's currency. Omit to leave unchanged. |
| `createSubscriptions` | array<object> | no | Subscriptions to add, each with its products, in the shape POST crm/quotes takes. |
| `createSubscriptions[].termType` | any | yes | Whether the subscription runs to a fixed end date or renews indefinitely. One of: `"termed"`, `"evergreen"`. |
| `createSubscriptions[].serviceStartDate` | date | yes | The first date the subscription delivers service. Format YYYY-MM-DD. |
| `createSubscriptions[].serviceEndDate` | date | no | The last date the subscription delivers service. Format YYYY-MM-DD. Required on a termed subscription. |
| `createSubscriptions[].autoRenew` | boolean | no | Whether the subscription renews automatically at the end of its term. |
| `createSubscriptions[].renewalTerm` | number | no | The renewal term in months. |
| `createSubscriptions[].quoteProducts` | array<object> | yes | The products in this subscription. |
| `createSubscriptions[].quoteProducts[].productId` | string | yes | The catalog product. See id on GET accounting/products/:id. |
| `createSubscriptions[].quoteProducts[].isRampDeal` | boolean | no | Whether this product is priced as a ramp deal. |
| `createSubscriptions[].quoteProducts[].rampInterval` | any | no | How the ramp steps. Only with isRampDeal. One of: `"annually"`, `"specificDates"`. |
| `createSubscriptions[].quoteProducts[].rampInvoiceTiming` | any | no | How a ramp deal is invoiced. Only with isRampDeal. One of: `"allAtOnce"`, `"perInterval"`. |
| `createSubscriptions[].quoteProducts[].quoteProductLines` | array<object> | yes | The priced lines of this quote product, at least one. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].productLineId` | string | yes | The catalog product line to price. It must belong to productId. See id on GET accounting/product-lines/:id. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].quantity` | decimal | no | The quantity, as a count, not an amount. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].discountAmount` | decimal | no | The per-unit discount, in the quote's currency. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].discountPercentage` | decimal | no | The per-unit discount off the list price on a 0-100 scale, so 10 means ten percent. Stored as a 0-1 fraction, which is what GET crm/quotes/:id returns. Used only when neither unitPrice nor discountAmount is sent. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].cappedPrice` | decimal | no | The ceiling on what this line may total, in the quote's currency. Billable-time and travel-expense lines only. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].invoiceFrequency` | any | no | How often this line is invoiced. One of: `"monthly"`, `"biMonthly"`, `"quarterly"`, `"semiAnnually"`, `"annually"`, `"once"`, `"custom"`, `"template"`, `"milestone"`, `"allAtOnce"`, `"termEnd"`. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].priceModel` | any | no | How the price is derived from quantity. Tiered and volume models need lineTiers, rateCard needs rateCardEntries. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].pricingTerm` | any | no | The period the unit price is quoted for. One of: `"monthly"`, `"biMonthly"`, `"once"`, `"quarterly"`, `"semiAnnually"`, `"annually"`. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].unitOfMeasure` | any | no | The unit the quantity is counted in. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].overConsumptionBehavior` | any | no | What happens when consumption exceeds a prepaid balance. Prepaid lines only. One of: `"allowNegative"`, `"overage"`. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].rolloverAtRenewal` | boolean | no | Whether an unused prepaid balance carries forward at renewal. Prepaid lines only. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].serviceStartDate` | date | no | The first date this line delivers service. Format YYYY-MM-DD. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].serviceEndDate` | date | no | The last date this line delivers service. Format YYYY-MM-DD. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].orderIndex` | number | no | The position of this line within its quote product, for display ordering. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].lineTiers` | array<object> | no | The pricing bands of a tiered, volume or stairstep line. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].lineTiers[].fromQuantity` | decimal | yes | The lower bound of the band, inclusive. A quantity, not an amount. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].lineTiers[].toQuantity` | decimal | no | The upper bound of the band, inclusive. Omit on the top band. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].lineTiers[].priceModel` | any | yes | How this band prices. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].lineTiers[].unitPrice` | decimal | no | The per-unit price for this band after discount, in the quote's currency. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].lineTiers[].listPrice` | decimal | no | The per-unit list price for this band before discount, in the quote's currency. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].rateCardEntries` | array<object> | no | The rate-card pricing of a rateCard line, one entry per billable component. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].rateCardEntries[].billableComponentId` | string | no | The billable component this entry prices. There is no endpoint for it. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].rateCardEntries[].description` | string | no | A label that distinguishes entries that otherwise have the same data. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].rateCardEntries[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].rateCardEntries[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].rateCardEntries[].unitOfMeasure` | any | yes | The unit the price is quoted per. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].rateCardEntries[].quantity` | decimal | no | The quantity of billable units, as a count, not an amount. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].rateCardEntries[].usageType` | any | no | What the usage represents. One of: `"consumption"`, `"overage"`, `"thresholdCounter"`, `"payg"`. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].rateCardEntries[].conversion` | decimal | no | The factor that converts usage units to billable units. A ratio, not an amount. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].rateCardEntries[].billableUnitOfMeasure` | any | no | The unit the entry is billed in, when it differs from unitOfMeasure. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].invoiceMilestones` | array<object> | no | The invoice milestones of a line invoiced by milestone. Their totals must add up to the line total. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].invoiceMilestones[].description` | string | no | What the milestone covers. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].invoiceMilestones[].totalPrice` | decimal | no | The amount invoiced at this milestone, in the quote's currency. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].invoiceMilestones[].percentage` | decimal | no | The share of the line total this milestone invoices. |
| `createSubscriptions[].quoteProducts[].quoteProductLines[].invoiceMilestones[].projectedDate` | date | no | The date the milestone is expected to be reached. Format YYYY-MM-DD. |
| `updateSubscriptions` | array<object> | no | Changes to existing subscriptions, each matched by id. Example: `[{"id":"c2e1f4a7-8b90-4d33-9a15-6f7e8d2b0c41","updateQuoteProducts":[{"id":"d4f2a1b8-3c67-4e05-8b92-1a7d0e6c5f38","updateQuoteProductLines":[{"id":"f6b4c3d0-5e89-4a27-8d14-3c9f2a8e7b50","quantity":"120"}]}]}]`. |
| `updateSubscriptions[].id` | string | yes | The identifier of the subscription on this quote. |
| `updateSubscriptions[].termType` | any | no | Whether the subscription runs to a fixed end date or renews indefinitely. Omit to leave unchanged. One of: `"termed"`, `"evergreen"`. |
| `updateSubscriptions[].serviceStartDate` | date | no | The first date the subscription delivers service. Format YYYY-MM-DD. Omit to leave unchanged. |
| `updateSubscriptions[].serviceEndDate` | date | no | The last date the subscription delivers service. Format YYYY-MM-DD. Omit to leave unchanged. |
| `updateSubscriptions[].autoRenew` | boolean | no | Whether the subscription renews automatically. Omit to leave unchanged. |
| `updateSubscriptions[].renewalTerm` | number | no | The renewal term in months. Omit to leave unchanged. |
| `updateSubscriptions[].createQuoteProducts` | array<object> | no | Products to add to this subscription. |
| `updateSubscriptions[].createQuoteProducts[].productId` | string | yes | The catalog product. See id on GET accounting/products/:id. |
| `updateSubscriptions[].createQuoteProducts[].isRampDeal` | boolean | no | Whether this product is priced as a ramp deal. |
| `updateSubscriptions[].createQuoteProducts[].rampInterval` | any | no | How the ramp steps. Only with isRampDeal. One of: `"annually"`, `"specificDates"`. |
| `updateSubscriptions[].createQuoteProducts[].rampInvoiceTiming` | any | no | How a ramp deal is invoiced. Only with isRampDeal. One of: `"allAtOnce"`, `"perInterval"`. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines` | array<object> | yes | The priced lines of this quote product, at least one. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].productLineId` | string | yes | The catalog product line to price. It must belong to productId. See id on GET accounting/product-lines/:id. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].quantity` | decimal | no | The quantity, as a count, not an amount. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].discountAmount` | decimal | no | The per-unit discount, in the quote's currency. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].discountPercentage` | decimal | no | The per-unit discount off the list price on a 0-100 scale, so 10 means ten percent. Stored as a 0-1 fraction, which is what GET crm/quotes/:id returns. Used only when neither unitPrice nor discountAmount is sent. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].cappedPrice` | decimal | no | The ceiling on what this line may total, in the quote's currency. Billable-time and travel-expense lines only. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].invoiceFrequency` | any | no | How often this line is invoiced. One of: `"monthly"`, `"biMonthly"`, `"quarterly"`, `"semiAnnually"`, `"annually"`, `"once"`, `"custom"`, `"template"`, `"milestone"`, `"allAtOnce"`, `"termEnd"`. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].priceModel` | any | no | How the price is derived from quantity. Tiered and volume models need lineTiers, rateCard needs rateCardEntries. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].pricingTerm` | any | no | The period the unit price is quoted for. One of: `"monthly"`, `"biMonthly"`, `"once"`, `"quarterly"`, `"semiAnnually"`, `"annually"`. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].unitOfMeasure` | any | no | The unit the quantity is counted in. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].overConsumptionBehavior` | any | no | What happens when consumption exceeds a prepaid balance. Prepaid lines only. One of: `"allowNegative"`, `"overage"`. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].rolloverAtRenewal` | boolean | no | Whether an unused prepaid balance carries forward at renewal. Prepaid lines only. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].serviceStartDate` | date | no | The first date this line delivers service. Format YYYY-MM-DD. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].serviceEndDate` | date | no | The last date this line delivers service. Format YYYY-MM-DD. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].orderIndex` | number | no | The position of this line within its quote product, for display ordering. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].lineTiers` | array<object> | no | The pricing bands of a tiered, volume or stairstep line. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].lineTiers[].fromQuantity` | decimal | yes | The lower bound of the band, inclusive. A quantity, not an amount. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].lineTiers[].toQuantity` | decimal | no | The upper bound of the band, inclusive. Omit on the top band. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].lineTiers[].priceModel` | any | yes | How this band prices. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].lineTiers[].unitPrice` | decimal | no | The per-unit price for this band after discount, in the quote's currency. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].lineTiers[].listPrice` | decimal | no | The per-unit list price for this band before discount, in the quote's currency. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].rateCardEntries` | array<object> | no | The rate-card pricing of a rateCard line, one entry per billable component. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].rateCardEntries[].billableComponentId` | string | no | The billable component this entry prices. There is no endpoint for it. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].rateCardEntries[].description` | string | no | A label that distinguishes entries that otherwise have the same data. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].rateCardEntries[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].rateCardEntries[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].rateCardEntries[].unitOfMeasure` | any | yes | The unit the price is quoted per. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].rateCardEntries[].quantity` | decimal | no | The quantity of billable units, as a count, not an amount. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].rateCardEntries[].usageType` | any | no | What the usage represents. One of: `"consumption"`, `"overage"`, `"thresholdCounter"`, `"payg"`. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].rateCardEntries[].conversion` | decimal | no | The factor that converts usage units to billable units. A ratio, not an amount. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].rateCardEntries[].billableUnitOfMeasure` | any | no | The unit the entry is billed in, when it differs from unitOfMeasure. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].invoiceMilestones` | array<object> | no | The invoice milestones of a line invoiced by milestone. Their totals must add up to the line total. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].invoiceMilestones[].description` | string | no | What the milestone covers. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].invoiceMilestones[].totalPrice` | decimal | no | The amount invoiced at this milestone, in the quote's currency. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].invoiceMilestones[].percentage` | decimal | no | The share of the line total this milestone invoices. |
| `updateSubscriptions[].createQuoteProducts[].quoteProductLines[].invoiceMilestones[].projectedDate` | date | no | The date the milestone is expected to be reached. Format YYYY-MM-DD. |
| `updateSubscriptions[].updateQuoteProducts` | array<object> | no | Changes to products of this subscription, each matched by id. |
| `updateSubscriptions[].updateQuoteProducts[].id` | string | yes | The identifier of the quote product in this subscription. |
| `updateSubscriptions[].updateQuoteProducts[].isRampDeal` | boolean | no | Whether this product is priced as a ramp deal. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].rampInterval` | any | no | How the ramp steps. Omit to leave unchanged. One of: `"annually"`, `"specificDates"`. |
| `updateSubscriptions[].updateQuoteProducts[].rampInvoiceTiming` | any | no | How a ramp deal is invoiced. Omit to leave unchanged. One of: `"allAtOnce"`, `"perInterval"`. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines` | array<object> | no | Lines to add to this quote product. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].productLineId` | string | yes | The catalog product line to price. It must belong to the quote product's product. See id on GET accounting/product-lines/:id. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].quantity` | decimal | no | The quantity, as a count, not an amount. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].discountAmount` | decimal | no | The per-unit discount, in the quote's currency. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].discountPercentage` | decimal | no | The per-unit discount off the list price on a 0-100 scale, so 10 means ten percent. Stored as a 0-1 fraction, which is what GET crm/quotes/:id returns. Used only when neither unitPrice nor discountAmount is sent. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].cappedPrice` | decimal | no | The ceiling on what this line may total, in the quote's currency. Billable-time and travel-expense lines only. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].invoiceFrequency` | any | no | How often this line is invoiced. One of: `"monthly"`, `"biMonthly"`, `"quarterly"`, `"semiAnnually"`, `"annually"`, `"once"`, `"custom"`, `"template"`, `"milestone"`, `"allAtOnce"`, `"termEnd"`. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].priceModel` | any | no | How the price is derived from quantity. Tiered and volume models need lineTiers, rateCard needs rateCardEntries. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].pricingTerm` | any | no | The period the unit price is quoted for. One of: `"monthly"`, `"biMonthly"`, `"once"`, `"quarterly"`, `"semiAnnually"`, `"annually"`. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].unitOfMeasure` | any | no | The unit the quantity is counted in. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].overConsumptionBehavior` | any | no | What happens when consumption exceeds a prepaid balance. Prepaid lines only. One of: `"allowNegative"`, `"overage"`. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].rolloverAtRenewal` | boolean | no | Whether an unused prepaid balance carries forward at renewal. Prepaid lines only. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].serviceStartDate` | date | no | The first date this line delivers service. Format YYYY-MM-DD. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].serviceEndDate` | date | no | The last date this line delivers service. Format YYYY-MM-DD. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].orderIndex` | number | no | The position of this line within its quote product, for display ordering. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].lineTiers` | array<object> | no | The pricing bands of a tiered, volume or stairstep line. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].lineTiers[].fromQuantity` | decimal | yes | The lower bound of the band, inclusive. A quantity, not an amount. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].lineTiers[].toQuantity` | decimal | no | The upper bound of the band, inclusive. Omit on the top band. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].lineTiers[].priceModel` | any | yes | How this band prices. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].lineTiers[].unitPrice` | decimal | no | The per-unit price for this band after discount, in the quote's currency. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].lineTiers[].listPrice` | decimal | no | The per-unit list price for this band before discount, in the quote's currency. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].rateCardEntries` | array<object> | no | The rate-card pricing of a rateCard line, one entry per billable component. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].rateCardEntries[].billableComponentId` | string | no | The billable component this entry prices. There is no endpoint for it. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].rateCardEntries[].description` | string | no | A label that distinguishes entries that otherwise have the same data. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].rateCardEntries[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].rateCardEntries[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].rateCardEntries[].unitOfMeasure` | any | yes | The unit the price is quoted per. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].rateCardEntries[].quantity` | decimal | no | The quantity of billable units, as a count, not an amount. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].rateCardEntries[].usageType` | any | no | What the usage represents. One of: `"consumption"`, `"overage"`, `"thresholdCounter"`, `"payg"`. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].rateCardEntries[].conversion` | decimal | no | The factor that converts usage units to billable units. A ratio, not an amount. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].rateCardEntries[].billableUnitOfMeasure` | any | no | The unit the entry is billed in, when it differs from unitOfMeasure. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].invoiceMilestones` | array<object> | no | The invoice milestones of a line invoiced by milestone. Their totals must add up to the line total. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].invoiceMilestones[].description` | string | no | What the milestone covers. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].invoiceMilestones[].totalPrice` | decimal | no | The amount invoiced at this milestone, in the quote's currency. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].invoiceMilestones[].percentage` | decimal | no | The share of the line total this milestone invoices. |
| `updateSubscriptions[].updateQuoteProducts[].createQuoteProductLines[].invoiceMilestones[].projectedDate` | date | no | The date the milestone is expected to be reached. Format YYYY-MM-DD. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines` | array<object> | no | Changes to lines of this quote product, each matched by id. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].id` | string | yes | The identifier of the line on this quote product. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].quantity` | decimal | no | The quantity, as a count, not an amount. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].discountAmount` | decimal | no | The per-unit discount, in the quote's currency. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].discountPercentage` | decimal | no | The per-unit discount off the list price on a 0-100 scale, so 10 means ten percent. Stored as a 0-1 fraction, which is what GET crm/quotes/:id returns. Used only when neither unitPrice nor discountAmount is sent. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].cappedPrice` | decimal | no | The ceiling on what this line may total, in the quote's currency. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].invoiceFrequency` | any | no | How often this line is invoiced. Omit to leave unchanged. One of: `"monthly"`, `"biMonthly"`, `"quarterly"`, `"semiAnnually"`, `"annually"`, `"once"`, `"custom"`, `"template"`, `"milestone"`, `"allAtOnce"`, `"termEnd"`. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].priceModel` | any | no | How the price is derived from quantity. Omit to leave unchanged. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].pricingTerm` | any | no | The period the unit price is quoted for. Omit to leave unchanged. One of: `"monthly"`, `"biMonthly"`, `"once"`, `"quarterly"`, `"semiAnnually"`, `"annually"`. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].unitOfMeasure` | any | no | The unit the quantity is counted in. Omit to leave unchanged. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].overConsumptionBehavior` | any | no | What happens when consumption exceeds a prepaid balance. Omit to leave unchanged. One of: `"allowNegative"`, `"overage"`. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].rolloverAtRenewal` | boolean | no | Whether an unused prepaid balance carries forward at renewal. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].serviceStartDate` | date | no | The first date this line delivers service. Format YYYY-MM-DD. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].serviceEndDate` | date | no | The last date this line delivers service. Format YYYY-MM-DD. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].orderIndex` | number | no | The position of this line within its quote product. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].lineTiers` | array<object> | no | The line's pricing bands, replacing the current ones. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].lineTiers[].fromQuantity` | decimal | yes | The lower bound of the band, inclusive. A quantity, not an amount. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].lineTiers[].toQuantity` | decimal | no | The upper bound of the band, inclusive. Omit on the top band. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].lineTiers[].priceModel` | any | yes | How this band prices. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].lineTiers[].unitPrice` | decimal | no | The per-unit price for this band after discount, in the quote's currency. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].lineTiers[].listPrice` | decimal | no | The per-unit list price for this band before discount, in the quote's currency. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].rateCardEntries` | array<object> | no | The line's rate-card entries, replacing the current set: an entry with an id updates that entry, one without adds an entry, and a current entry left out is deleted. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].rateCardEntries[].id` | string | no | The identifier of a rate-card entry already on this line, to change it in place; the fields sent overwrite its values and the others are kept. Omit to add a new entry. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].rateCardEntries[].billableComponentId` | string | no | The billable component this entry prices. There is no endpoint for it. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].rateCardEntries[].description` | string | no | A label that distinguishes entries that otherwise have the same data. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].rateCardEntries[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].rateCardEntries[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].rateCardEntries[].unitOfMeasure` | any | yes | The unit the price is quoted per. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].rateCardEntries[].quantity` | decimal | no | The quantity of billable units, as a count, not an amount. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].rateCardEntries[].usageType` | any | no | What the usage represents. One of: `"consumption"`, `"overage"`, `"thresholdCounter"`, `"payg"`. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].rateCardEntries[].conversion` | decimal | no | The factor that converts usage units to billable units. A ratio, not an amount. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].rateCardEntries[].billableUnitOfMeasure` | any | no | The unit the entry is billed in, when it differs from unitOfMeasure. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].invoiceMilestones` | array<object> | no | The line's invoice milestones, replacing the current ones. Omit to leave unchanged. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].invoiceMilestones[].description` | string | no | What the milestone covers. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].invoiceMilestones[].totalPrice` | decimal | no | The amount invoiced at this milestone, in the quote's currency. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].invoiceMilestones[].percentage` | decimal | no | The share of the line total this milestone invoices. |
| `updateSubscriptions[].updateQuoteProducts[].updateQuoteProductLines[].invoiceMilestones[].projectedDate` | date | no | The date the milestone is expected to be reached. Format YYYY-MM-DD. |
| `updateSubscriptions[].updateQuoteProducts[].deleteQuoteProductLines` | array<string> | no | Identifiers of lines of this quote product to remove. |
| `updateSubscriptions[].deleteQuoteProducts` | array<string> | no | Identifiers of products of this subscription to remove, with their lines. |
| `deleteSubscriptions` | array<string> | no | Identifiers of subscriptions to remove, with their products. |
| `createNonRecurringProducts` | array<object> | no | Products outside any subscription to add, in the shape POST crm/quotes takes. |
| `createNonRecurringProducts[].productId` | string | yes | The catalog product. See id on GET accounting/products/:id. |
| `createNonRecurringProducts[].quoteProductLines` | array<object> | yes | The priced lines of this quote product, at least one. |
| `createNonRecurringProducts[].quoteProductLines[].productLineId` | string | yes | The catalog product line to price. It must belong to productId. See id on GET accounting/product-lines/:id. |
| `createNonRecurringProducts[].quoteProductLines[].quantity` | decimal | no | The quantity, as a count, not an amount. |
| `createNonRecurringProducts[].quoteProductLines[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. |
| `createNonRecurringProducts[].quoteProductLines[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. |
| `createNonRecurringProducts[].quoteProductLines[].discountAmount` | decimal | no | The per-unit discount, in the quote's currency. |
| `createNonRecurringProducts[].quoteProductLines[].discountPercentage` | decimal | no | The per-unit discount off the list price on a 0-100 scale, so 10 means ten percent. Stored as a 0-1 fraction, which is what GET crm/quotes/:id returns. Used only when neither unitPrice nor discountAmount is sent. |
| `createNonRecurringProducts[].quoteProductLines[].cappedPrice` | decimal | no | The ceiling on what this line may total, in the quote's currency. Billable-time and travel-expense lines only. |
| `createNonRecurringProducts[].quoteProductLines[].invoiceFrequency` | any | no | How often this line is invoiced. One of: `"monthly"`, `"biMonthly"`, `"quarterly"`, `"semiAnnually"`, `"annually"`, `"once"`, `"custom"`, `"template"`, `"milestone"`, `"allAtOnce"`, `"termEnd"`. |
| `createNonRecurringProducts[].quoteProductLines[].priceModel` | any | no | How the price is derived from quantity. Tiered and volume models need lineTiers, rateCard needs rateCardEntries. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `createNonRecurringProducts[].quoteProductLines[].pricingTerm` | any | no | The period the unit price is quoted for. One of: `"monthly"`, `"biMonthly"`, `"once"`, `"quarterly"`, `"semiAnnually"`, `"annually"`. |
| `createNonRecurringProducts[].quoteProductLines[].unitOfMeasure` | any | no | The unit the quantity is counted in. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `createNonRecurringProducts[].quoteProductLines[].overConsumptionBehavior` | any | no | What happens when consumption exceeds a prepaid balance. Prepaid lines only. One of: `"allowNegative"`, `"overage"`. |
| `createNonRecurringProducts[].quoteProductLines[].rolloverAtRenewal` | boolean | no | Whether an unused prepaid balance carries forward at renewal. Prepaid lines only. |
| `createNonRecurringProducts[].quoteProductLines[].serviceStartDate` | date | no | The first date this line delivers service. Format YYYY-MM-DD. |
| `createNonRecurringProducts[].quoteProductLines[].serviceEndDate` | date | no | The last date this line delivers service. Format YYYY-MM-DD. |
| `createNonRecurringProducts[].quoteProductLines[].orderIndex` | number | no | The position of this line within its quote product, for display ordering. |
| `createNonRecurringProducts[].quoteProductLines[].lineTiers` | array<object> | no | The pricing bands of a tiered, volume or stairstep line. |
| `createNonRecurringProducts[].quoteProductLines[].lineTiers[].fromQuantity` | decimal | yes | The lower bound of the band, inclusive. A quantity, not an amount. |
| `createNonRecurringProducts[].quoteProductLines[].lineTiers[].toQuantity` | decimal | no | The upper bound of the band, inclusive. Omit on the top band. |
| `createNonRecurringProducts[].quoteProductLines[].lineTiers[].priceModel` | any | yes | How this band prices. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `createNonRecurringProducts[].quoteProductLines[].lineTiers[].unitPrice` | decimal | no | The per-unit price for this band after discount, in the quote's currency. |
| `createNonRecurringProducts[].quoteProductLines[].lineTiers[].listPrice` | decimal | no | The per-unit list price for this band before discount, in the quote's currency. |
| `createNonRecurringProducts[].quoteProductLines[].rateCardEntries` | array<object> | no | The rate-card pricing of a rateCard line, one entry per billable component. |
| `createNonRecurringProducts[].quoteProductLines[].rateCardEntries[].billableComponentId` | string | no | The billable component this entry prices. There is no endpoint for it. |
| `createNonRecurringProducts[].quoteProductLines[].rateCardEntries[].description` | string | no | A label that distinguishes entries that otherwise have the same data. |
| `createNonRecurringProducts[].quoteProductLines[].rateCardEntries[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. |
| `createNonRecurringProducts[].quoteProductLines[].rateCardEntries[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. |
| `createNonRecurringProducts[].quoteProductLines[].rateCardEntries[].unitOfMeasure` | any | yes | The unit the price is quoted per. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `createNonRecurringProducts[].quoteProductLines[].rateCardEntries[].quantity` | decimal | no | The quantity of billable units, as a count, not an amount. |
| `createNonRecurringProducts[].quoteProductLines[].rateCardEntries[].usageType` | any | no | What the usage represents. One of: `"consumption"`, `"overage"`, `"thresholdCounter"`, `"payg"`. |
| `createNonRecurringProducts[].quoteProductLines[].rateCardEntries[].conversion` | decimal | no | The factor that converts usage units to billable units. A ratio, not an amount. |
| `createNonRecurringProducts[].quoteProductLines[].rateCardEntries[].billableUnitOfMeasure` | any | no | The unit the entry is billed in, when it differs from unitOfMeasure. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `createNonRecurringProducts[].quoteProductLines[].invoiceMilestones` | array<object> | no | The invoice milestones of a line invoiced by milestone. Their totals must add up to the line total. |
| `createNonRecurringProducts[].quoteProductLines[].invoiceMilestones[].description` | string | no | What the milestone covers. |
| `createNonRecurringProducts[].quoteProductLines[].invoiceMilestones[].totalPrice` | decimal | no | The amount invoiced at this milestone, in the quote's currency. |
| `createNonRecurringProducts[].quoteProductLines[].invoiceMilestones[].percentage` | decimal | no | The share of the line total this milestone invoices. |
| `createNonRecurringProducts[].quoteProductLines[].invoiceMilestones[].projectedDate` | date | no | The date the milestone is expected to be reached. Format YYYY-MM-DD. |
| `updateNonRecurringProducts` | array<object> | no | Changes to products outside any subscription, each matched by id. |
| `updateNonRecurringProducts[].id` | string | yes | The identifier of the quote product outside any subscription. |
| `updateNonRecurringProducts[].createQuoteProductLines` | array<object> | no | Lines to add to this quote product. |
| `updateNonRecurringProducts[].createQuoteProductLines[].productLineId` | string | yes | The catalog product line to price. It must belong to the quote product's product. See id on GET accounting/product-lines/:id. |
| `updateNonRecurringProducts[].createQuoteProductLines[].quantity` | decimal | no | The quantity, as a count, not an amount. |
| `updateNonRecurringProducts[].createQuoteProductLines[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. |
| `updateNonRecurringProducts[].createQuoteProductLines[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. |
| `updateNonRecurringProducts[].createQuoteProductLines[].discountAmount` | decimal | no | The per-unit discount, in the quote's currency. |
| `updateNonRecurringProducts[].createQuoteProductLines[].discountPercentage` | decimal | no | The per-unit discount off the list price on a 0-100 scale, so 10 means ten percent. Stored as a 0-1 fraction, which is what GET crm/quotes/:id returns. Used only when neither unitPrice nor discountAmount is sent. |
| `updateNonRecurringProducts[].createQuoteProductLines[].cappedPrice` | decimal | no | The ceiling on what this line may total, in the quote's currency. Billable-time and travel-expense lines only. |
| `updateNonRecurringProducts[].createQuoteProductLines[].invoiceFrequency` | any | no | How often this line is invoiced. One of: `"monthly"`, `"biMonthly"`, `"quarterly"`, `"semiAnnually"`, `"annually"`, `"once"`, `"custom"`, `"template"`, `"milestone"`, `"allAtOnce"`, `"termEnd"`. |
| `updateNonRecurringProducts[].createQuoteProductLines[].priceModel` | any | no | How the price is derived from quantity. Tiered and volume models need lineTiers, rateCard needs rateCardEntries. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `updateNonRecurringProducts[].createQuoteProductLines[].pricingTerm` | any | no | The period the unit price is quoted for. One of: `"monthly"`, `"biMonthly"`, `"once"`, `"quarterly"`, `"semiAnnually"`, `"annually"`. |
| `updateNonRecurringProducts[].createQuoteProductLines[].unitOfMeasure` | any | no | The unit the quantity is counted in. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateNonRecurringProducts[].createQuoteProductLines[].overConsumptionBehavior` | any | no | What happens when consumption exceeds a prepaid balance. Prepaid lines only. One of: `"allowNegative"`, `"overage"`. |
| `updateNonRecurringProducts[].createQuoteProductLines[].rolloverAtRenewal` | boolean | no | Whether an unused prepaid balance carries forward at renewal. Prepaid lines only. |
| `updateNonRecurringProducts[].createQuoteProductLines[].serviceStartDate` | date | no | The first date this line delivers service. Format YYYY-MM-DD. |
| `updateNonRecurringProducts[].createQuoteProductLines[].serviceEndDate` | date | no | The last date this line delivers service. Format YYYY-MM-DD. |
| `updateNonRecurringProducts[].createQuoteProductLines[].orderIndex` | number | no | The position of this line within its quote product, for display ordering. |
| `updateNonRecurringProducts[].createQuoteProductLines[].lineTiers` | array<object> | no | The pricing bands of a tiered, volume or stairstep line. |
| `updateNonRecurringProducts[].createQuoteProductLines[].lineTiers[].fromQuantity` | decimal | yes | The lower bound of the band, inclusive. A quantity, not an amount. |
| `updateNonRecurringProducts[].createQuoteProductLines[].lineTiers[].toQuantity` | decimal | no | The upper bound of the band, inclusive. Omit on the top band. |
| `updateNonRecurringProducts[].createQuoteProductLines[].lineTiers[].priceModel` | any | yes | How this band prices. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `updateNonRecurringProducts[].createQuoteProductLines[].lineTiers[].unitPrice` | decimal | no | The per-unit price for this band after discount, in the quote's currency. |
| `updateNonRecurringProducts[].createQuoteProductLines[].lineTiers[].listPrice` | decimal | no | The per-unit list price for this band before discount, in the quote's currency. |
| `updateNonRecurringProducts[].createQuoteProductLines[].rateCardEntries` | array<object> | no | The rate-card pricing of a rateCard line, one entry per billable component. |
| `updateNonRecurringProducts[].createQuoteProductLines[].rateCardEntries[].billableComponentId` | string | no | The billable component this entry prices. There is no endpoint for it. |
| `updateNonRecurringProducts[].createQuoteProductLines[].rateCardEntries[].description` | string | no | A label that distinguishes entries that otherwise have the same data. |
| `updateNonRecurringProducts[].createQuoteProductLines[].rateCardEntries[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. |
| `updateNonRecurringProducts[].createQuoteProductLines[].rateCardEntries[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. |
| `updateNonRecurringProducts[].createQuoteProductLines[].rateCardEntries[].unitOfMeasure` | any | yes | The unit the price is quoted per. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateNonRecurringProducts[].createQuoteProductLines[].rateCardEntries[].quantity` | decimal | no | The quantity of billable units, as a count, not an amount. |
| `updateNonRecurringProducts[].createQuoteProductLines[].rateCardEntries[].usageType` | any | no | What the usage represents. One of: `"consumption"`, `"overage"`, `"thresholdCounter"`, `"payg"`. |
| `updateNonRecurringProducts[].createQuoteProductLines[].rateCardEntries[].conversion` | decimal | no | The factor that converts usage units to billable units. A ratio, not an amount. |
| `updateNonRecurringProducts[].createQuoteProductLines[].rateCardEntries[].billableUnitOfMeasure` | any | no | The unit the entry is billed in, when it differs from unitOfMeasure. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateNonRecurringProducts[].createQuoteProductLines[].invoiceMilestones` | array<object> | no | The invoice milestones of a line invoiced by milestone. Their totals must add up to the line total. |
| `updateNonRecurringProducts[].createQuoteProductLines[].invoiceMilestones[].description` | string | no | What the milestone covers. |
| `updateNonRecurringProducts[].createQuoteProductLines[].invoiceMilestones[].totalPrice` | decimal | no | The amount invoiced at this milestone, in the quote's currency. |
| `updateNonRecurringProducts[].createQuoteProductLines[].invoiceMilestones[].percentage` | decimal | no | The share of the line total this milestone invoices. |
| `updateNonRecurringProducts[].createQuoteProductLines[].invoiceMilestones[].projectedDate` | date | no | The date the milestone is expected to be reached. Format YYYY-MM-DD. |
| `updateNonRecurringProducts[].updateQuoteProductLines` | array<object> | no | Changes to lines of this quote product, each matched by id. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].id` | string | yes | The identifier of the line on this quote product. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].quantity` | decimal | no | The quantity, as a count, not an amount. Omit to leave unchanged. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. Omit to leave unchanged. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. Omit to leave unchanged. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].discountAmount` | decimal | no | The per-unit discount, in the quote's currency. Omit to leave unchanged. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].discountPercentage` | decimal | no | The per-unit discount off the list price on a 0-100 scale, so 10 means ten percent. Stored as a 0-1 fraction, which is what GET crm/quotes/:id returns. Used only when neither unitPrice nor discountAmount is sent. Omit to leave unchanged. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].cappedPrice` | decimal | no | The ceiling on what this line may total, in the quote's currency. Omit to leave unchanged. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].invoiceFrequency` | any | no | How often this line is invoiced. Omit to leave unchanged. One of: `"monthly"`, `"biMonthly"`, `"quarterly"`, `"semiAnnually"`, `"annually"`, `"once"`, `"custom"`, `"template"`, `"milestone"`, `"allAtOnce"`, `"termEnd"`. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].priceModel` | any | no | How the price is derived from quantity. Omit to leave unchanged. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].pricingTerm` | any | no | The period the unit price is quoted for. Omit to leave unchanged. One of: `"monthly"`, `"biMonthly"`, `"once"`, `"quarterly"`, `"semiAnnually"`, `"annually"`. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].unitOfMeasure` | any | no | The unit the quantity is counted in. Omit to leave unchanged. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].overConsumptionBehavior` | any | no | What happens when consumption exceeds a prepaid balance. Omit to leave unchanged. One of: `"allowNegative"`, `"overage"`. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].rolloverAtRenewal` | boolean | no | Whether an unused prepaid balance carries forward at renewal. Omit to leave unchanged. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].serviceStartDate` | date | no | The first date this line delivers service. Format YYYY-MM-DD. Omit to leave unchanged. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].serviceEndDate` | date | no | The last date this line delivers service. Format YYYY-MM-DD. Omit to leave unchanged. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].orderIndex` | number | no | The position of this line within its quote product. Omit to leave unchanged. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].lineTiers` | array<object> | no | The line's pricing bands, replacing the current ones. Omit to leave unchanged. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].lineTiers[].fromQuantity` | decimal | yes | The lower bound of the band, inclusive. A quantity, not an amount. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].lineTiers[].toQuantity` | decimal | no | The upper bound of the band, inclusive. Omit on the top band. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].lineTiers[].priceModel` | any | yes | How this band prices. One of: `"flat"`, `"perUnit"`, `"tiered"`, `"volume"`, `"stairstep"`, `"rateCard"`, `"thresholdBased"`. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].lineTiers[].unitPrice` | decimal | no | The per-unit price for this band after discount, in the quote's currency. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].lineTiers[].listPrice` | decimal | no | The per-unit list price for this band before discount, in the quote's currency. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].rateCardEntries` | array<object> | no | The line's rate-card entries, replacing the current set: an entry with an id updates that entry, one without adds an entry, and a current entry left out is deleted. Omit to leave unchanged. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].rateCardEntries[].id` | string | no | The identifier of a rate-card entry already on this line, to change it in place; the fields sent overwrite its values and the others are kept. Omit to add a new entry. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].rateCardEntries[].billableComponentId` | string | no | The billable component this entry prices. There is no endpoint for it. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].rateCardEntries[].description` | string | no | A label that distinguishes entries that otherwise have the same data. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].rateCardEntries[].unitPrice` | decimal | no | The per-unit price after discount, in the quote's currency. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].rateCardEntries[].listPrice` | decimal | no | The per-unit list price before discount, in the quote's currency. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].rateCardEntries[].unitOfMeasure` | any | yes | The unit the price is quoted per. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].rateCardEntries[].quantity` | decimal | no | The quantity of billable units, as a count, not an amount. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].rateCardEntries[].usageType` | any | no | What the usage represents. One of: `"consumption"`, `"overage"`, `"thresholdCounter"`, `"payg"`. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].rateCardEntries[].conversion` | decimal | no | The factor that converts usage units to billable units. A ratio, not an amount. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].rateCardEntries[].billableUnitOfMeasure` | any | no | The unit the entry is billed in, when it differs from unitOfMeasure. One of: `"instance"`, `"gigabyte"`, `"terabyte"`, `"user"`, `"seat"`, `"minute"`, `"hour"`, `"day"`, `"month"`, `"each"`, `"license"`, `"activeUser"`, `"megabyte"`, `"message"`, `"text"`, `"platform"`, `"employee"`, `"personnel"`, `"credit"`, `"currency"`, `"package"`, `"case"`, `"word"`, `"record"`. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].invoiceMilestones` | array<object> | no | The line's invoice milestones, replacing the current ones. Omit to leave unchanged. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].invoiceMilestones[].description` | string | no | What the milestone covers. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].invoiceMilestones[].totalPrice` | decimal | no | The amount invoiced at this milestone, in the quote's currency. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].invoiceMilestones[].percentage` | decimal | no | The share of the line total this milestone invoices. |
| `updateNonRecurringProducts[].updateQuoteProductLines[].invoiceMilestones[].projectedDate` | date | no | The date the milestone is expected to be reached. Format YYYY-MM-DD. |
| `updateNonRecurringProducts[].deleteQuoteProductLines` | array<string> | no | Identifiers of lines of this quote product to remove. |
| `deleteNonRecurringProducts` | array<string> | no | Identifiers of products outside any subscription to remove, with their lines. Example: `["d0f8a7b4-9c23-4e61-8b58-7a3d6e2c1f94"]`. |

```json
{
  "quoteDate": "2026-01-15",
  "serviceStartDate": "2026-01-15",
  "paymentTerm": "<paymentTerm>",
  "billToAddressId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "soldToAddressId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "isPrimary": true,
  "memo": "Renegotiated after the pilot.",
  "signDate": "2026-01-15",
  "oneTimeDiscountAmount": "19.99",
  "oneTimeDiscountAllocation": "firstInvoice",
  "billableTimeCappedPrice": "19.99",
  "createSubscriptions": [
    {
      "termType": "termed",
      "serviceStartDate": "2026-01-15",
      "serviceEndDate": "2026-01-15",
      "autoRenew": true,
      "renewalTerm": 0,
      "quoteProducts": [
        {
          "productId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
          "isRampDeal": true,
          "rampInterval": "annually",
          "rampInvoiceTiming": "allAtOnce",
          "quoteProductLines": [
            {
              "productLineId": null,
              "quantity": null,
              "listPrice": null,
              "unitPrice": null,
              "discountAmount": null,
              "discountPercentage": null,
              "cappedPrice": null,
              "invoiceFrequency": null,
              "priceModel": null,
              "pricingTerm": null,
              "unitOfMeasure": null,
              "overConsumptionBehavior": null,
              "rolloverAtRenewal": null,
              "serviceStartDate": null,
              "serviceEndDate": null,
              "orderIndex": null,
              "lineTiers": null,
              "rateCardEntries": null,
              "invoiceMilestones": null
            }
          ]
        }
      ]
    }
  ],
  "updateSubscriptions": [
    {
      "id": "c2e1f4a7-8b90-4d33-9a15-6f7e8d2b0c41",
      "updateQuoteProducts": [
        {
          "id": "d4f2a1b8-3c67-4e05-8b92-1a7d0e6c5f38",
          "updateQuoteProductLines": [
            {
              "id": "f6b4c3d0-5e89-4a27-8d14-3c9f2a8e7b50",
              "quantity": "120"
            }
          ]
        }
      ]
    }
  ],
  "deleteSubscriptions": [
    "<deleteSubscriptions>"
  ],
  "createNonRecurringProducts": [
    {
      "productId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "quoteProductLines": [
        {
          "productLineId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
          "quantity": "19.99",
          "listPrice": "19.99",
          "unitPrice": "19.99",
          "discountAmount": "19.99",
          "discountPercentage": "19.99",
          "cappedPrice": "19.99",
          "invoiceFrequency": "monthly",
          "priceModel": "flat",
          "pricingTerm": "monthly",
          "unitOfMeasure": "instance",
          "overConsumptionBehavior": "allowNegative",
          "rolloverAtRenewal": true,
          "serviceStartDate": "2026-01-15",
          "serviceEndDate": "2026-01-15",
          "orderIndex": 0,
          "lineTiers": [
            {
              "fromQuantity": null,
              "toQuantity": null,
              "priceModel": null,
              "unitPrice": null,
              "listPrice": null
            }
          ],
          "rateCardEntries": [
            {
              "billableComponentId": null,
              "description": null,
              "unitPrice": null,
              "listPrice": null,
              "unitOfMeasure": null,
              "quantity": null,
              "usageType": null,
              "conversion": null,
              "billableUnitOfMeasure": null
            }
          ],
          "invoiceMilestones": [
            {
              "description": null,
              "totalPrice": null,
              "percentage": null,
              "projectedDate": null
            }
          ]
        }
      ]
    }
  ],
  "updateNonRecurringProducts": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "createQuoteProductLines": [
        {
          "productLineId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
          "quantity": "19.99",
          "listPrice": "19.99",
          "unitPrice": "19.99",
          "discountAmount": "19.99",
          "discountPercentage": "19.99",
          "cappedPrice": "19.99",
          "invoiceFrequency": "monthly",
          "priceModel": "flat",
          "pricingTerm": "monthly",
          "unitOfMeasure": "instance",
          "overConsumptionBehavior": "allowNegative",
          "rolloverAtRenewal": true,
          "serviceStartDate": "2026-01-15",
          "serviceEndDate": "2026-01-15",
          "orderIndex": 0,
          "lineTiers": [
            {
              "fromQuantity": null,
              "toQuantity": null,
              "priceModel": null,
              "unitPrice": null,
              "listPrice": null
            }
          ],
          "rateCardEntries": [
            {
              "billableComponentId": null,
              "description": null,
              "unitPrice": null,
              "listPrice": null,
              "unitOfMeasure": null,
              "quantity": null,
              "usageType": null,
              "conversion": null,
              "billableUnitOfMeasure": null
            }
          ],
          "invoiceMilestones": [
            {
              "description": null,
              "totalPrice": null,
              "percentage": null,
              "projectedDate": null
            }
          ]
        }
      ],
      "updateQuoteProductLines": [
        {
          "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
          "quantity": "19.99",
          "listPrice": "19.99",
          "unitPrice": "19.99",
          "discountAmount": "19.99",
          "discountPercentage": "19.99",
          "cappedPrice": "19.99",
          "invoiceFrequency": "monthly",
          "priceModel": "flat",
          "pricingTerm": "monthly",
          "unitOfMeasure": "instance",
          "overConsumptionBehavior": "allowNegative",
          "rolloverAtRenewal": true,
          "serviceStartDate": "2026-01-15",
          "serviceEndDate": "2026-01-15",
          "orderIndex": 0,
          "lineTiers": [
            {
              "fromQuantity": null,
              "toQuantity": null,
              "priceModel": null,
              "unitPrice": null,
              "listPrice": null
            }
          ],
          "rateCardEntries": [
            {
              "id": null,
              "billableComponentId": null,
              "description": null,
              "unitPrice": null,
              "listPrice": null,
              "unitOfMeasure": null,
              "quantity": null,
              "usageType": null,
              "conversion": null,
              "billableUnitOfMeasure": null
            }
          ],
          "invoiceMilestones": [
            {
              "description": null,
              "totalPrice": null,
              "percentage": null,
              "projectedDate": null
            }
          ]
        }
      ],
      "deleteQuoteProductLines": [
        "<deleteQuoteProductLines>"
      ]
    }
  ],
  "deleteNonRecurringProducts": [
    "d0f8a7b4-9c23-4e61-8b58-7a3d6e2c1f94"
  ]
}
```

## Response

`200` Success

```json
{
  "data": {},
  "diagnostics": [
    {
      "code": "<code>",
      "message": "<message>",
      "severity": "error",
      "path": [
        "<path>"
      ],
      "details": "<details>"
    }
  ]
}
```

## Response headers

- `Idempotency-Replayed` — Present and `true` only when this response replays a previously stored one for the same Idempotency-Key, rather than reflecting a live execution. Absent on a live response - never sent as `false`.

## Errors

| Code | Status |
| --- | --- |
| `NOT_FOUND` | 400 |
| `QUOTE_LOCKED` | 400 |
| `PRIMARY_REQUIRED` | 400 |
| `REFERENCE_NOT_FOUND` | 400 |
| `UNKNOWN_CHILD` | 400 |
| `CONFLICTING_OPERATIONS` | 400 |
| `INVALID_PRODUCT_LINE` | 400 |
| `PRICE_REQUIRED` | 400 |
| `QUOTE_TYPE_MISMATCH` | 400 |
| `VALIDATION_FAILED` | 400 |
| `IDEMPOTENCY_KEY_CONFLICT` | 409 |
| `IDEMPOTENCY_PAYLOAD_MISMATCH` | 422 |

## Statuses

- `400` — Invalid request or business failure. Codes: NOT_FOUND, QUOTE_LOCKED, PRIMARY_REQUIRED, REFERENCE_NOT_FOUND, UNKNOWN_CHILD, CONFLICTING_OPERATIONS, INVALID_PRODUCT_LINE, PRICE_REQUIRED, QUOTE_TYPE_MISMATCH, VALIDATION_FAILED
- `401` — The request carries no valid access token.
- `403` — Not authorized
- `404` — Not found
- `409` — The Idempotency-Key is still being processed by another request.
- `422` — The Idempotency-Key was already used with a different request payload.
- `429` — Too many requests from this client address. The response has no body and no `Retry-After` header.
- `500` — Internal server error
