Partially update a sales order

PATCH /accounting/sales-orders/{id}

Group: Accounting › Sales Orders · Operation ID: updateSalesOrder

Writes only the fields the request body carries. Everything omitted is left exactly as it was. Product lines are edited through three parallel arrays: createProducts adds new lines, updateProducts rewrites existing ones (matched by salesOrderProductLineId, omitted fields left unchanged), and deleteProducts removes them by id; createSubscriptions adds new subscriptions with their own lines. A new Commit with Overage line requires allowance (its Allowance & Overage terms, defaulting from the product catalog); other line types reject it, and updateProducts cannot change an existing line's allowance. While an order is pending approval the whole header and its lines are editable. Once approved only a small set of header fields may change, and updateProducts entries may carry nothing but salesOrderProductLineId and tags; any other field or product operation fails with APPROVED_FIELD_LOCKED. An unknown id fails with NOT_FOUND; a product line id that does not belong to the order fails with INVALID_LINE. Runs in a transaction, so a failure leaves the order untouched.

Open in the interactive reference

Parameters

Name In Type Required Description
Api-Version header "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 UUID of the sales order to update. The selector, never itself changed.

Request body

Required, application/json: updateSalesOrderInput.

Field Type Required Description
billToAddressId string no UUID of the Address invoices for this order go to. An address that does not exist fails with INVALID_ADDRESS. Stays editable after the order is approved.
createProducts array of object no Product lines to add to the order. Locked once the order is approved: sending it then fails with APPROVED_FIELD_LOCKED.
createProducts[].allowance LineAllowance no The Allowance & Overage terms of a Commit with Overage line. Required for that line type and rejected on any other; omitted fields default from the product catalog.
createProducts[].allowance.allowance string (decimal) yes Committed quantity per allowance term, in the catalog Allowance's unit of measure.
createProducts[].allowance.allowanceTerm string no The period the allowance covers: monthly, biMonthly, quarterly, semiAnnually, annually or orderTerm. Defaults to the product catalog's Allowance term.
createProducts[].allowance.maximumRolloverLimit string (decimal) no Cap on the quantity that may roll over. Accepted only when the catalog Allowance has rollover enabled, and defaults to its setting.
createProducts[].allowance.overage LineOverage no Discount and invoicing overrides for the line's overage. Omit it to take everything from the catalog Overage and its price-book entry.
createProducts[].allowance.overage.discountAmount string (decimal) no Discount per unit off the overage price, in the order currency. Takes precedence over discountPercentage when both are sent; omit both to price the overage exactly as its price-book entry has it.
createProducts[].allowance.overage.discountPercentage string (decimal) no Discount per unit off the overage price on a 0–100 scale, so 10 means ten percent. Used only when discountAmount is not given.
createProducts[].allowance.overage.invoiceTiming string no Whether the overage invoices advance (at the start of its period) or arrears (after it). Defaults from the entity's active invoice policy for overage lines, then from the parent line.
createProducts[].allowance.overage.lineInvoiceDay string no Which day of the period the overage invoices on: anniversary, first, last or specific. Defaults from the entity's active invoice policy for overage lines, then from the parent line.
createProducts[].allowance.rolloverDuration string (decimal) no How many allowance terms unused allowance rolls over for. Accepted only when the catalog Allowance has rollover enabled, and defaults to its setting.
createProducts[].discountAmount string (decimal) no Discount per unit off listPrice, in the order currency. Used when no unitPrice is given, and then drives the other two.
createProducts[].discountPercentage string (decimal) no Discount per unit off listPrice on a 0–100 scale, so 10 means ten percent. Stored as a 0–1 fraction. The lowest precedence of the three — used only when neither unitPrice nor discountAmount is given.
createProducts[].externalIdentifiers array of object no Identifiers this line carries in other systems, upserted by fieldName.
createProducts[].externalIdentifiers[].externalUrl string no Deep link to the record in the owning system, shown beside the id.
createProducts[].externalIdentifiers[].fieldName string yes Names the ExternalIdentifierConfiguration this id belongs to, as that configuration spells it. It must already be configured for the tenant; an unknown name is rejected. Identifiers are upserted by this name, so sending it again overwrites the stored value.
createProducts[].externalIdentifiers[].value string yes The identifier as the owning system spells it.
createProducts[].invoiceFrequency string no How often the line invoices — an InvoiceFrequency member: monthly, biMonthly, quarterly, semiAnnually, annually, once, custom, template, milestone, allAtOnce or termEnd. Defaults to the product line's own setting.
createProducts[].invoiceTiming string no Whether the line invoices advance (at the start of the service period) or arrears (after it). Defaults from the entity's active invoice policy for this line type.
createProducts[].lineInvoiceDay string no Which day of the period the line invoices on: anniversary, first, last or specific. Defaults from the entity's active invoice policy.
createProducts[].listPrice string (decimal) no Undiscounted price per unit, in the order currency. Defaults to the list price the order's price book holds for this product line, and is the figure the other pricing fields are reconciled against.
createProducts[].priceModel string no How the line is priced: flat, perUnit, tiered, volume, stairstep or rateCard. Defaults to the product line's own model. tiered, volume and stairstep take their prices from tiers and rateCard from rateCardEntries, so for those the line-level discount fields are not reconciled. thresholdBased is rejected: it needs a base line plus a metered usage child, which this endpoint does not build.
createProducts[].pricingTerm string no The period the price is quoted for: monthly, biMonthly, quarterly, semiAnnually, annually or once. Defaults to the product line's own term.
createProducts[].productLineId string yes UUID of the ProductLine being added. It settles the product, the line type and the billing rules every omitted field defaults from.
createProducts[].quantity string (decimal) no Number of units ordered. Required unless the line takes its quantity from somewhere else: usage-metered line types (PayAsYouGo, Usage, Billable*) meter it from usage records and tier-priced models (tiered, volume, stairstep, thresholdBased) derive it from the tier structure, so for those it defaults to zero. Anywhere else, omitting it fails the request.
createProducts[].rateCardEntries array of object no Per-unit rates for a rateCard-priced line. Supplying any entry moves pricing onto the rate card, so the line-level discount fields stop being reconciled.
createProducts[].rateCardEntries[].billableComponentId string no UUID of the BillableComponent this row meters. Optional — a row may price a unit of measure without naming a component — but a UUID that does not resolve rejects the whole request.
createProducts[].rateCardEntries[].conversion string (decimal) no Factor converting the billable unit into the reporting unit — 1000 when usage is metered per call but reported per thousand.
createProducts[].rateCardEntries[].description string no Free-text label for the row, carried through to the stored rate-card entry.
createProducts[].rateCardEntries[].listPrice string (decimal) no Undiscounted rate per unitOfMeasure, in the order currency. Honoured only while the product line's enforceListPrice is false; otherwise the product line's own list price wins.
createProducts[].rateCardEntries[].unitOfMeasure string yes The unit this row is priced in.
createProducts[].rateCardEntries[].unitPrice string (decimal) yes Negotiated rate per unitOfMeasure, in the order currency.
createProducts[].serviceEndDate string (date) no Last day of the line's service period. The order's own service end is the latest across all its lines, and is left open on an evergreen order.
createProducts[].serviceStartDate string (date) no First day of the line's service period. The order's own service start is the earliest across all its lines.
createProducts[].subscriptionId string no UUID of a subscription already on this order to hang the line under. Omit it to add the line to the order itself as a one-time line. A subscription that is not on the order fails with INVALID_SUBSCRIPTION.
createProducts[].tags array of object no Value-accounting tags to allocate this line by. Requires value-allocation tagging to be enabled for sales orders.
createProducts[].tags[].dimension string yes Name of the value-accounting dimension, as configured for the tenant. Resolved by name, not by id.
createProducts[].tags[].value string yes Name of the value within that dimension. The pair must resolve to an existing tag and the dimension must be enabled for sales orders; an unknown pair rejects the whole request.
createProducts[].tiers array of object no The pricing tiers of a tiered, volume or stairstep line. The ranges must be contiguous, and the last tier is left open-ended by omitting its toQuantity.
createProducts[].tiers[].fromQuantity string (decimal) yes Lower bound of the tier's quantity range, inclusive.
createProducts[].tiers[].listPrice string (decimal) no Undiscounted price for this tier, in the order currency. Defaults to unitPrice, i.e. no discount on the tier.
createProducts[].tiers[].priceModel string no How unitPrice applies within the tier: perUnit (the default) charges it for every unit in the range, flat charges it once for the whole tier.
createProducts[].tiers[].toQuantity string (decimal) no Upper bound of the tier's quantity range. Omit it on the last tier to leave the range open-ended.
createProducts[].tiers[].unitPrice string (decimal) yes Negotiated price for this tier, in the order currency. Charged per unit in the range when priceModel is perUnit, or once for the whole tier when it is flat.
createProducts[].totalPrice string (decimal) no Total for the line, in the order currency. Persisted exactly as supplied rather than recomputed — omit it and the line's own pricing drives the total.
createProducts[].unitOfMeasure string no The unit the line is priced and metered in. Defaults to the product line's own unit.
createProducts[].unitPrice string (decimal) no Negotiated price per unit, in the order currency. The highest precedence of the three pricing inputs — supply it and discountAmount and discountPercentage are recomputed from it (discountAmount = listPrice − unitPrice).
createSubscriptions array of object no New subscriptions to add to the order, each bringing its own product lines. Locked once the order is approved: sending it then fails with APPROVED_FIELD_LOCKED.
createSubscriptions[].autoRenew boolean no Whether the subscription renews itself at the end of its term.
createSubscriptions[].products array of ProductLine yes The recurring product lines of the new subscription. Every one must be a subscription-based product line, or the request fails with INVALID_SUBSCRIPTION_PRODUCT.
createSubscriptions[].products[].allowance LineAllowance no The Allowance & Overage terms of a Commit with Overage line. Required for that line type and rejected on any other; omitted fields default from the product catalog.
createSubscriptions[].products[].allowance.allowance string (decimal) yes Committed quantity per allowance term, in the catalog Allowance's unit of measure.
createSubscriptions[].products[].allowance.allowanceTerm string no The period the allowance covers: monthly, biMonthly, quarterly, semiAnnually, annually or orderTerm. Defaults to the product catalog's Allowance term.
createSubscriptions[].products[].allowance.maximumRolloverLimit string (decimal) no Cap on the quantity that may roll over. Accepted only when the catalog Allowance has rollover enabled, and defaults to its setting.
createSubscriptions[].products[].allowance.overage LineOverage no Discount and invoicing overrides for the line's overage. Omit it to take everything from the catalog Overage and its price-book entry.
createSubscriptions[].products[].allowance.overage.discountAmount string (decimal) no Discount per unit off the overage price, in the order currency. Takes precedence over discountPercentage when both are sent; omit both to price the overage exactly as its price-book entry has it.
createSubscriptions[].products[].allowance.overage.discountPercentage string (decimal) no Discount per unit off the overage price on a 0–100 scale, so 10 means ten percent. Used only when discountAmount is not given.
createSubscriptions[].products[].allowance.overage.invoiceTiming string no Whether the overage invoices advance (at the start of its period) or arrears (after it). Defaults from the entity's active invoice policy for overage lines, then from the parent line.
createSubscriptions[].products[].allowance.overage.lineInvoiceDay string no Which day of the period the overage invoices on: anniversary, first, last or specific. Defaults from the entity's active invoice policy for overage lines, then from the parent line.
createSubscriptions[].products[].allowance.rolloverDuration string (decimal) no How many allowance terms unused allowance rolls over for. Accepted only when the catalog Allowance has rollover enabled, and defaults to its setting.
createSubscriptions[].products[].discountAmount string (decimal) no Discount per unit off listPrice, in the order currency. Used when no unitPrice is given, and then drives the other two.
createSubscriptions[].products[].discountPercentage string (decimal) no Discount per unit off listPrice on a 0–100 scale, so 10 means ten percent. Stored as a 0–1 fraction. The lowest precedence of the three — used only when neither unitPrice nor discountAmount is given.
createSubscriptions[].products[].externalIdentifiers array of ExternalIdentifier no Identifiers this line carries in other systems, upserted by fieldName.
createSubscriptions[].products[].externalIdentifiers[].externalUrl string no Deep link to the record in the owning system, shown beside the id.
createSubscriptions[].products[].externalIdentifiers[].fieldName string yes Names the ExternalIdentifierConfiguration this id belongs to, as that configuration spells it. It must already be configured for the tenant; an unknown name is rejected. Identifiers are upserted by this name, so sending it again overwrites the stored value.
createSubscriptions[].products[].externalIdentifiers[].value string yes The identifier as the owning system spells it.
createSubscriptions[].products[].invoiceFrequency string no How often the line invoices — an InvoiceFrequency member: monthly, biMonthly, quarterly, semiAnnually, annually, once, custom, template, milestone, allAtOnce or termEnd. Defaults to the product line's own setting.
createSubscriptions[].products[].invoiceFrequencyTemplateId string no UUID of the invoice frequency template.
createSubscriptions[].products[].invoiceTiming string no Whether the line invoices advance (at the start of the service period) or arrears (after it). Defaults from the entity's active invoice policy for this line type.
createSubscriptions[].products[].lineInvoiceDay string no Which day of the period the line invoices on: anniversary, first, last or specific. Defaults from the entity's active invoice policy.
createSubscriptions[].products[].listPrice string (decimal) no Undiscounted price per unit, in the order currency. Defaults to the list price the order's price book holds for this product line, and is the figure the other pricing fields are reconciled against.
createSubscriptions[].products[].priceModel string no How the line is priced: flat, perUnit, tiered, volume, stairstep or rateCard. Defaults to the product line's own model. tiered, volume and stairstep take their prices from tiers and rateCard from rateCardEntries, so for those the line-level discount fields are not reconciled. thresholdBased is rejected: it needs a base line plus a metered usage child, which this endpoint does not build.
createSubscriptions[].products[].pricingTerm string no The period the price is quoted for: monthly, biMonthly, quarterly, semiAnnually, annually or once. Defaults to the product line's own term.
createSubscriptions[].products[].productLineId string yes UUID of the ProductLine being ordered. It settles the product, the line type and the billing rules every omitted field defaults from. It must exist, and it must not be threshold-based or prepaid: those need a base line plus a metered usage child under one product, which this endpoint does not build.
createSubscriptions[].products[].quantity string (decimal) no Number of units ordered. Required unless the line takes its quantity from somewhere else: usage-metered line types (PayAsYouGo, Usage, Billable*) meter it from usage records and tier-priced models (tiered, volume, stairstep, thresholdBased) derive it from the tier structure, so for those it defaults to zero. Anywhere else, omitting it fails the request.
createSubscriptions[].products[].rateCardEntries array of RateCardEntry no Per-unit rates for a rateCard-priced line. Supplying any entry moves pricing onto the rate card, so the line-level discount fields stop being reconciled.
createSubscriptions[].products[].rateCardEntries[].billableComponentId string no UUID of the BillableComponent this row meters. Optional — a row may price a unit of measure without naming a component — but a UUID that does not resolve rejects the whole request.
createSubscriptions[].products[].rateCardEntries[].conversion string (decimal) no Factor converting the billable unit into the reporting unit — 1000 when usage is metered per call but reported per thousand.
createSubscriptions[].products[].rateCardEntries[].description string no Free-text label for the row, carried through to the stored rate-card entry.
createSubscriptions[].products[].rateCardEntries[].listPrice string (decimal) no Undiscounted rate per unitOfMeasure, in the order currency. Honoured only while the product line's enforceListPrice is false; otherwise the product line's own list price wins.
createSubscriptions[].products[].rateCardEntries[].unitOfMeasure string yes The unit this row is priced in.
createSubscriptions[].products[].rateCardEntries[].unitPrice string (decimal) yes Negotiated rate per unitOfMeasure, in the order currency.
createSubscriptions[].products[].serviceEndDate string (date) no Last day of the line's service period. The order's own service end is the latest across all its lines, and is left open on an evergreen order.
createSubscriptions[].products[].serviceStartDate string (date) no First day of the line's service period. The order's own service start is the earliest across all its lines.
createSubscriptions[].products[].tags array of LineTag no Value-accounting tags to allocate this line by. Requires value-allocation tagging to be enabled for sales orders.
createSubscriptions[].products[].tags[].dimension string yes Name of the value-accounting dimension, as configured for the tenant. Resolved by name, not by id.
createSubscriptions[].products[].tags[].value string yes Name of the value within that dimension. The pair must resolve to an existing tag and the dimension must be enabled for sales orders; an unknown pair rejects the whole request.
createSubscriptions[].products[].tiers array of LineTier no The pricing tiers of a tiered, volume or stairstep line. The ranges must be contiguous, and the last tier is left open-ended by omitting its toQuantity.
createSubscriptions[].products[].tiers[].fromQuantity string (decimal) yes Lower bound of the tier's quantity range, inclusive.
createSubscriptions[].products[].tiers[].listPrice string (decimal) no Undiscounted price for this tier, in the order currency. Defaults to unitPrice, i.e. no discount on the tier.
createSubscriptions[].products[].tiers[].priceModel string no How unitPrice applies within the tier: perUnit (the default) charges it for every unit in the range, flat charges it once for the whole tier.
createSubscriptions[].products[].tiers[].toQuantity string (decimal) no Upper bound of the tier's quantity range. Omit it on the last tier to leave the range open-ended.
createSubscriptions[].products[].tiers[].unitPrice string (decimal) yes Negotiated price for this tier, in the order currency. Charged per unit in the range when priceModel is perUnit, or once for the whole tier when it is flat.
createSubscriptions[].products[].totalPrice string (decimal) no Total for the line, in the order currency. Persisted exactly as supplied rather than recomputed — omit it and the line's own pricing drives the total.
createSubscriptions[].products[].unitOfMeasure string no The unit the line is priced and metered in. Defaults to the product line's own unit.
createSubscriptions[].products[].unitPrice string (decimal) no Negotiated price per unit, in the order currency. The highest precedence of the three pricing inputs — supply it and discountAmount and discountPercentage are recomputed from it (discountAmount = listPrice − unitPrice).
createSubscriptions[].serviceEndDate string (date) no Last day the subscription is in service. Omit it on an evergreen subscription.
createSubscriptions[].serviceStartDate string (date) yes First day the subscription is in service.
createSubscriptions[].term string (decimal) no Intended length of a termed subscription in months. What actually bounds the subscription is serviceStartDate and serviceEndDate, so supply the end date to fix when it ends.
createSubscriptions[].termType string yes termed for a subscription of fixed length, evergreen for an open-ended one that keeps renewing.
deleteProducts array of string no UUIDs of product lines to remove from the order. Each must belong to it, or the request fails with INVALID_LINE. Locked once the order is approved: sending it then fails with APPROVED_FIELD_LOCKED.
effectiveDate string (date) no Day the order becomes commercially effective. Stays editable after the order is approved.
excludeFromTaxEngine boolean no Whether the order is kept out of the tax engine, so no tax is calculated for it. Locked once the order is approved: sending it then fails with APPROVED_FIELD_LOCKED.
oneTimeDiscountAllocation string no How the one-time discount is spread across the order's invoices: firstInvoice puts all of it on the first, alignToInvoiceFrequency spreads it over the invoicing schedule, custom leaves the allocation to be set by hand. Locked once the order is approved: sending it then fails with APPROVED_FIELD_LOCKED.
oneTimeDiscountAmount string (decimal) no A one-off discount on the order as a whole, in the order currency. Independent of the per-line discount fields. Locked once the order is approved: sending it then fails with APPROVED_FIELD_LOCKED.
opportunityName string no Name of the opportunity the order came out of. Stays editable after the order is approved.
paymentTermCode string no The order's payment term, named by its code. Stays editable after the order is approved.
purchaseOrder string no The customer's own purchase-order number for this order. Stays editable after the order is approved.
serviceEndDate string (date) no Last day of the order's service period. Locked once the order is approved: sending it then fails with APPROVED_FIELD_LOCKED.
serviceStartDate string (date) no First day of the order's service period. Locked once the order is approved: sending it then fails with APPROVED_FIELD_LOCKED.
signDate string (date) no Day the order was signed. Stays editable after the order is approved.
soldToAddressId string no UUID of the Address of the contracting party. An address that does not exist fails with INVALID_ADDRESS. Stays editable after the order is approved.
updateProducts array of object no Changes to product lines already on the order, each matched by its salesOrderProductLineId. Fields left out of an entry keep their current values. Once the order is approved an entry may carry only salesOrderProductLineId and tags; any other field then fails with APPROVED_FIELD_LOCKED.
updateProducts[].discountAmount string (decimal) no Discount per unit off listPrice, in the order currency. This endpoint has no unitPrice field, so the discount is what drives it: unitPrice = listPrice − discountAmount. Takes precedence over discountPercentage.
updateProducts[].discountPercentage string (decimal) no Discount per unit off listPrice on a 0–100 scale, so 10 means ten percent. Stored as a 0–1 fraction. Used only when discountAmount is absent.
updateProducts[].externalIdentifiers array of object no Identifiers to set on the line, upserted by fieldName. Names not listed are left as they are — there is no way to remove one.
updateProducts[].externalIdentifiers[].externalUrl string no Deep link to the record in the owning system, shown beside the id.
updateProducts[].externalIdentifiers[].fieldName string yes Names the ExternalIdentifierConfiguration this id belongs to, as that configuration spells it. It must already be configured for the tenant; an unknown name is rejected. Identifiers are upserted by this name, so sending it again overwrites the stored value.
updateProducts[].externalIdentifiers[].value string yes The identifier as the owning system spells it.
updateProducts[].invoiceFrequency string no New invoicing frequency for the line — an InvoiceFrequency member: monthly, biMonthly, quarterly, semiAnnually, annually, once, custom, template, milestone, allAtOnce or termEnd. Omit it to leave the frequency as it stands.
updateProducts[].invoiceTiming string no Whether the line invoices advance (at the start of the service period) or arrears (after it). Omit it to leave the timing as it stands.
updateProducts[].lineInvoiceDay string no Which day of the period the line invoices on: anniversary, first, last or specific. Omit it to leave the day as it stands.
updateProducts[].listPrice string (decimal) no New undiscounted price per unit, in the order currency. Changing it on its own still re-reconciles the line: the existing discount amount is held fixed and unitPrice and discountPercentage are re-derived against the new list price.
updateProducts[].quantity string (decimal) no New number of units for the line. Omit it to leave the quantity as it stands.
updateProducts[].rateCardEntries array of object no Replaces the line's rate-card rows: a row carrying an id is updated, one without is added, and any existing row whose id is not in the list is deleted. Omit the field entirely to leave the line's rows untouched.
updateProducts[].rateCardEntries[].billableComponentId string no UUID of the BillableComponent this row meters. Optional — a row may price a unit of measure without naming a component — but a UUID that does not resolve rejects the whole request.
updateProducts[].rateCardEntries[].conversion string (decimal) no Factor converting the billable unit into the reporting unit — 1000 when usage is metered per call but reported per thousand.
updateProducts[].rateCardEntries[].description string no Free-text label for the row, carried through to the stored rate-card entry.
updateProducts[].rateCardEntries[].id string no UUID of a rate-card row already on this line, to change it in place. Leave it out to add a new row. An id that is not on the line fails the request and nothing is applied.
updateProducts[].rateCardEntries[].listPrice string (decimal) no Undiscounted rate per unitOfMeasure, in the order currency. Honoured only while the product line's enforceListPrice is false; otherwise the product line's own list price wins.
updateProducts[].rateCardEntries[].unitOfMeasure string yes The unit this row is priced in.
updateProducts[].rateCardEntries[].unitPrice string (decimal) yes Negotiated rate per unitOfMeasure, in the order currency.
updateProducts[].salesOrderProductLineId string yes UUID of the order's product line to change. It must belong to this order, or the request fails with INVALID_LINE.
updateProducts[].serviceEndDate string (date) no New last day of the line's service period.
updateProducts[].serviceStartDate string (date) no New first day of the line's service period.
updateProducts[].tags array of object no Replaces the line's value-accounting tags wholesale. Send [] to clear them; omit the field to leave them untouched. Lines that share one product (ramp deals) share their tags, so all of them must be sent the same set. Stays editable after the order is approved.
updateProducts[].tags[].dimension string yes Name of the value-accounting dimension, as configured for the tenant. Resolved by name, not by id.
updateProducts[].tags[].value string yes Name of the value within that dimension. The pair must resolve to an existing tag and the dimension must be enabled for sales orders; an unknown pair rejects the whole request.
updateProducts[].tiers array of object no Replaces the line's pricing tiers wholesale. Omit the field to leave them untouched.
updateProducts[].tiers[].fromQuantity string (decimal) yes Lower bound of the tier's quantity range, inclusive.
updateProducts[].tiers[].listPrice string (decimal) no Undiscounted price for this tier, in the order currency. Defaults to unitPrice, i.e. no discount on the tier.
updateProducts[].tiers[].priceModel string no How unitPrice applies within the tier: perUnit (the default) charges it for every unit in the range, flat charges it once for the whole tier.
updateProducts[].tiers[].toQuantity string (decimal) no Upper bound of the tier's quantity range. Omit it on the last tier to leave the range open-ended.
updateProducts[].tiers[].unitPrice string (decimal) yes Negotiated price for this tier, in the order currency. Charged per unit in the range when priceModel is perUnit, or once for the whole tier when it is flat.
updateProducts[].totalPrice string (decimal) no New total for the line, in the order currency. Persisted exactly as supplied rather than recomputed.

Example:

{
  "billToAddressId": "5b8c31f6-04ad-472e-9f81-63a0d7e295cb",
  "createProducts": [
    {
      "allowance": {
        "allowance": "1000",
        "allowanceTerm": "monthly",
        "maximumRolloverLimit": "500",
        "overage": {
          "discountAmount": "1.50",
          "discountPercentage": "10",
          "invoiceTiming": "arrears",
          "lineInvoiceDay": "anniversary"
        },
        "rolloverDuration": "2"
      },
      "discountAmount": "120.00",
      "discountPercentage": "10",
      "externalIdentifiers": [
        {
          "externalUrl": "https://netsuite.example.com/app/accounting/transactions/salesord.nl?id=10042",
          "fieldName": "netsuiteInternalId",
          "value": "SO-10042"
        }
      ],
      "invoiceFrequency": "monthly",
      "invoiceTiming": "advance",
      "lineInvoiceDay": "anniversary",
      "listPrice": "1200.00",
      "priceModel": "perUnit",
      "pricingTerm": "annually",
      "productLineId": "6a1f2c94-3d58-4b17-9e02-7c8ab4d5f610",
      "quantity": "10",
      "rateCardEntries": [
        {
          "billableComponentId": "9f1c2d34-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
          "conversion": "1000",
          "description": "API calls beyond the included volume",
          "listPrice": "0.005",
          "unitOfMeasure": "apiCall",
          "unitPrice": "0.004"
        }
      ],
      "serviceEndDate": "2026-12-31",
      "serviceStartDate": "2026-01-01",
      "subscriptionId": "c8402e17-95bf-4a63-8d20-71ec3f6a0b48",
      "tags": [
        {
          "dimension": "Department",
          "value": "Engineering"
        }
      ],
      "tiers": [
        {
          "fromQuantity": "0",
          "listPrice": "15.00",
          "priceModel": "perUnit",
          "toQuantity": "100",
          "unitPrice": "12.50"
        }
      ],
      "totalPrice": "12960.00",
      "unitOfMeasure": "seat",
      "unitPrice": "1080.00"
    }
  ],
  "createSubscriptions": [
    {
      "autoRenew": true,
      "products": [
        {
          "allowance": {
            "allowance": "1000",
            "allowanceTerm": "monthly",
            "maximumRolloverLimit": "500",
            "overage": {
              "discountAmount": null,
              "discountPercentage": null,
              "invoiceTiming": null,
              "lineInvoiceDay": null
            },
            "rolloverDuration": "2"
          },
          "discountAmount": "120.00",
          "discountPercentage": "10",
          "externalIdentifiers": [
            {
              "externalUrl": null,
              "fieldName": null,
              "value": null
            }
          ],
          "invoiceFrequency": "monthly",
          "invoiceFrequencyTemplateId": "9f1c2d34-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
          "invoiceTiming": "advance",
          "lineInvoiceDay": "anniversary",
          "listPrice": "1200.00",
          "priceModel": "perUnit",
          "pricingTerm": "annually",
          "productLineId": "6a1f2c94-3d58-4b17-9e02-7c8ab4d5f610",
          "quantity": "10",
          "rateCardEntries": [
            {
              "billableComponentId": null,
              "conversion": null,
              "description": null,
              "listPrice": null,
              "unitOfMeasure": null,
              "unitPrice": null
            }
          ],
          "serviceEndDate": "2026-12-31",
          "serviceStartDate": "2026-01-01",
          "tags": [
            {
              "dimension": null,
              "value": null
            }
          ],
          "tiers": [
            {
              "fromQuantity": null,
              "listPrice": null,
              "priceModel": null,
              "toQuantity": null,
              "unitPrice": null
            }
          ],
          "totalPrice": "12960.00",
          "unitOfMeasure": "seat",
          "unitPrice": "1080.00"
        }
      ],
      "serviceEndDate": "2026-12-31",
      "serviceStartDate": "2026-01-01",
      "term": "12",
      "termType": "termed"
    }
  ],
  "deleteProducts": [
    "<deleteProducts>"
  ],
  "effectiveDate": "2026-02-01",
  "excludeFromTaxEngine": true,
  "oneTimeDiscountAllocation": "firstInvoice",
  "oneTimeDiscountAmount": "500.00",
  "opportunityName": "Contoso — 2026 renewal",
  "paymentTermCode": "NET30",
  "purchaseOrder": "PO-2026-0042",
  "serviceEndDate": "2026-12-31",
  "serviceStartDate": "2026-01-01",
  "signDate": "2026-01-10",
  "soldToAddressId": "5b8c31f6-04ad-472e-9f81-63a0d7e295cb",
  "updateProducts": [
    {
      "discountAmount": "120.00",
      "discountPercentage": "10",
      "externalIdentifiers": [
        {
          "externalUrl": "https://netsuite.example.com/app/accounting/transactions/salesord.nl?id=10042",
          "fieldName": "netsuiteInternalId",
          "value": "SO-10042"
        }
      ],
      "invoiceFrequency": "monthly",
      "invoiceTiming": "advance",
      "lineInvoiceDay": "anniversary",
      "listPrice": "1200.00",
      "quantity": "10",
      "rateCardEntries": [
        {
          "billableComponentId": "9f1c2d34-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
          "conversion": "1000",
          "description": "API calls beyond the included volume",
          "id": "3f7b9a52-0c1d-48e6-b934-a5d720e8146f",
          "listPrice": "0.005",
          "unitOfMeasure": "apiCall",
          "unitPrice": "0.004"
        }
      ],
      "salesOrderProductLineId": "a05e7d13-8f62-4b90-bc47-1e63d0592a8f",
      "serviceEndDate": "2026-12-31",
      "serviceStartDate": "2026-01-01",
      "tags": [
        {
          "dimension": "Department",
          "value": "Engineering"
        }
      ],
      "tiers": [
        {
          "fromQuantity": "0",
          "listPrice": "15.00",
          "priceModel": "perUnit",
          "toQuantity": "100",
          "unitPrice": "12.50"
        }
      ],
      "totalPrice": "12960.00"
    }
  ]
}

Response

200 Success

Under data (updateSalesOrderOutput):

Field Type Required Description
approvalStatus string yes The order's approval status after the update: draft, pendingApproval, revise or approved.
id string yes UUID of the sales order that was updated.

Response headers

Errors

Code Status
APPROVED_FIELD_LOCKED 400
INVALID_ADDRESS 400
INVALID_LINE 400
INVALID_SUBSCRIPTION 400
INVALID_SUBSCRIPTION_PRODUCT 400
VALIDATION_FAILED 400
NOT_FOUND 404
IDEMPOTENCY_KEY_CONFLICT 409
IDEMPOTENCY_PAYLOAD_MISMATCH 422

Statuses