Modify or renew a subscription

Operation ID: modifySubscription

Group: Accounting › Subscriptions

Open in the interactive reference

POST /accounting/subscriptions/{id}/modify

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

Modifies or renews a subscription. When modificationType is 'midTermModification', the changes to lines take effect on modificationDate. You can add products, including tiered, rate-card and ramp pricing, increase quantities, cancel lines, and replace products.

Each 'midTermModification' request creates one subscription modification, whose id is subscriptionModificationId in the response. The request also creates one modification sales order, unless it only cancels lines.

When modificationType is 'renew', the whole subscription renews for another term that starts the day after the current service end date. The request creates one renewal sales order that copies the subscription's active lines.

When modificationType is 'earlyRenew', the new term starts early, on modificationDate, which must fall after the current term's start. The request creates one early-renewal sales order that copies the lines active the day before. On approval the current term ends on that date: its un-invoiced overlap is billed and its invoiced overlap is credited.

To cancel the whole subscription, use POST accounting/subscriptions/:id/cancel.

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 Id of the subscription to modify (a UUID); bound from the :id path segment. Must belong to customerId.

Request body

Required, application/json: modifySubscriptionInput.

Field Type Required Description
customerId string yes [fk: CustomerApi.customers.id] Id of the customer owning the subscription being modified (a UUID). The subscription must belong to this customer.
externalOrderId string yes Idempotency key assigned by the upstream system (e.g. CPQ order id). When the tenant has a SalesOrderExternalIdentifierConfiguration for fieldName externalOrderId, the value is stamped on the generated sales order and a resubmission is rejected with DUPLICATE_EXTERNAL_ORDER_ID; without that configuration duplicates are not detected.
modificationType any yes Discriminator for the kind of modification. midTermModification applies the line arrays (addLines/changeLines/cancelLines/replaceGroups) on the modificationDate. renew renews the whole subscription: it carries term/priceChangePercentage and must omit the line arrays and modificationDate. earlyRenew renews the whole subscription early: same shape as renew plus the required modificationDate. One of: "midTermModification", "renew", "earlyRenew".
bookDate date no Booking date for the generated sales order (ISO 8601, YYYY-MM-DD). Defaults to today for midTermModification and earlyRenew, and to the renewal service start date for renew.
effectiveDate date no Sales effective date stamped on the generated sales order (ISO 8601, YYYY-MM-DD). Defaults to the modificationDate. Not supported for renewal payloads.
oneTimeDiscountAmount decimal no Order-level one-time discount amount in the subscription currency. Not supported for renewal payloads.
oneTimeDiscountAllocation any no How the one-time discount is allocated across invoices (firstInvoice, alignToInvoiceFrequency). Not supported for renewal payloads. One of: "firstInvoice", "alignToInvoiceFrequency".
billToAddressId string no [fk: CustomerApi.customers.addresses.id] Bill-to address for the generated sales order (a UUID). Must belong to the customer. Defaults to the originating order's bill-to address. Not supported for renewal payloads.
soldToAddressId string no [fk: CustomerApi.customers.addresses.id] Sold-to address for the generated sales order (a UUID). Must belong to the customer. Defaults to the originating order's sold-to address. Not supported for renewal payloads.
signDate date no Date the modification was signed/agreed upstream (ISO 8601, YYYY-MM-DD)
purchaseOrder string no Customer purchase order reference
opportunityId string no Upstream opportunity identifier (e.g. Salesforce opportunity id)
opportunityName string no Upstream opportunity name
approvalStatus any no Approval status of the generated sales order. Authoritative upstream systems may pass approved to apply the modification without manual approval. Defaults to pendingApproval. One of: "pendingApproval", "approved".
externalizedCalculations boolean no midTermModification only. When true, the caller owns line totals: every addLines entry (top-level and in replaceGroups) and every rampDeal ramp must carry totalPrice (TOTAL_PRICE_REQUIRED), every changeLines entry must carry totalPrice for its added quantity (CHANGE_LINE_TOTAL_PRICE_REQUIRED) and may not target a ramp line (EXTERNALIZED_RAMP_CHANGE_NOT_SUPPORTED), the value is stored as given, and Everest does not recalculate it. Defaults to false, where totals are calculated by Everest and any totalPrice is ignored.
modificationDate date no Effective date of the modification (ISO 8601, YYYY-MM-DD). Required for midTermModification: service changes take effect on this date and it must fall within the subscription service period. Required for earlyRenew: the new term starts on this date, which must be after the current term's start date and no later than the service end date. Must be omitted for renew (the renewal starts the day after the current service end date).
term number no renew and earlyRenew only: renewal term in months. Defaults to the subscription's configured auto-renewal term; when neither is set a renewal is rejected with RENEWAL_TERM_MISSING.
priceChangePercentage decimal no renew and earlyRenew only: fractional price increase applied to the list and unit prices of every renewed line (0.05 = 5% increase; tiered lines keep their prices). Defaults to the subscription's configured auto-renewal price increase. Negative values are rejected.
note string no Free-text note. Recorded on the SubscriptionModification for midTermModification and on the renewal sales order for renew/earlyRenew.
addLines array<object> no New products to add to the subscription. Same pricing surface as SalesOrderApi.create subscription products (tiers, rate cards, ramp deals).
addLines[].productLineId string yes [fk: ProductLineApi.productLines.id] Id of the product line defining pricing and billing rules (a UUID)
addLines[].quantity decimal no Quantity of the product. Optional when (a) the line type sources quantity from usage records or external capture, or (b) rampDeal is provided (each ramp period carries its own quantity).
addLines[].invoiceFrequency any no Invoice frequency. Defaults to product line setting. One of: "monthly", "biMonthly", "quarterly", "semiAnnually", "annually", "once", "custom", "template", "milestone", "allAtOnce".
addLines[].invoiceTiming any no Invoice timing relative to service period (advance, arrears). Defaults to entity policy. One of: "advance", "arrears".
addLines[].lineInvoiceDay string no Specific day for generating invoices. Defaults to entity policy.
addLines[].priceModel any no Pricing model. Defaults to product line setting. One of: "flat", "perUnit", "tiered", "volume", "stairstep", "rateCard", "thresholdBased".
addLines[].unitOfMeasure any no Unit of measure (instance, gigabyte, terabyte, user, seat, minute, hour, day, month, each, license, activeUser, megabyte, message, text, platform, employee, personnel, credit, currency, package, case). Defaults to product line setting. One of: "instance", "gigabyte", "terabyte", "user", "seat", "minute", "hour", "day", "month", "each", "license", "activeUser", "megabyte", "message", "text", "platform", "employee", "personnel", "credit", "currency", "package", "case".
addLines[].listPrice decimal no Standard list price before discounts. Defaults to unitPrice when omitted; must be omitted when the product line has enforceListPrice set.
addLines[].unitPrice decimal no Actual unit price after applying discounts. Required unless rampDeal is provided.
addLines[].totalPrice decimal no Total price of the added line, stored as given. Required when externalizedCalculations is true unless rampDeal is provided (each ramp then carries its own totalPrice); ignored otherwise.
addLines[].altProductName string no Alternative product name stored on the created sales order product. Passed through as given.
addLines[].discount decimal no Discount value (interpreted based on discountType)
addLines[].discountType any no Discount type (amount, percentage) One of: "amount", "percentage".
addLines[].pricingTerm any no Pricing term period. Defaults to product line setting. One of: "monthly", "biMonthly", "once", "quarterly", "semiAnnually", "annually".
addLines[].tiers array<object> no Pricing tiers for tiered/volume/stairstep price models. Tiers must cover contiguous quantity ranges starting at 0; bounds are inclusive and each tier's fromQuantity must be exactly the previous tier's toQuantity + 1 (e.g. 0-100, 101-500, 501-open).
addLines[].tiers[].fromQuantity decimal yes Lower bound of quantity range (inclusive). First tier must start at 0.
addLines[].tiers[].toQuantity decimal no Upper bound of quantity range (inclusive). Omit on the last tier for open-ended ranges.
addLines[].tiers[].unitPrice decimal yes Per-unit price for quantities in this tier after discount
addLines[].tiers[].listPrice decimal no Per-unit list price before discount. Defaults to unitPrice.
addLines[].tiers[].priceModel any no Per-tier price model (flat, perUnit). Defaults to perUnit. One of: "flat", "perUnit".
addLines[].rateCardEntries array<object> no Rate card entries for this product line. Required when priceModel is rateCard and the product line has no template entries.
addLines[].rateCardEntries[].identifier string yes BillableComponent identifier for this meter
addLines[].rateCardEntries[].description string no Free-text description of the rate card entry
addLines[].rateCardEntries[].unitOfMeasure string yes Unit of measure for this meter
addLines[].rateCardEntries[].unitPrice decimal yes Per-unit rate negotiated for this modification
addLines[].rateCardEntries[].listPrice decimal no Per-unit list price. Honored only when product line enforceListPrice is false.
addLines[].rateCardEntries[].conversion decimal no Conversion factor between billable and reporting units
addLines[].rampDeal object no Ramp deal definition for phased additions. Mutually exclusive with top-level quantity/unitPrice.
addLines[].rampDeal.interval any yes How ramps are defined. annually = auto-derive yearly ramps; specificDates = caller provides explicit serviceStartDate/serviceEndDate per ramp. One of: "annually", "specificDates".
addLines[].rampDeal.invoiceTiming any yes perInterval invoices at each ramp start; allAtOnce invoices the whole deal upfront and requires every ramp invoiceFrequency = allAtOnce. One of: "perInterval", "allAtOnce".
addLines[].rampDeal.ramps array<object> yes One entry per ramp, in chronological order. Minimum 2 ramps.
addLines[].rampDeal.ramps[].serviceStartDate date no Ramp service start date (ISO 8601, YYYY-MM-DD). Required for specificDates; omit for annually.
addLines[].rampDeal.ramps[].serviceEndDate date no Ramp service end date (ISO 8601, YYYY-MM-DD). Required for specificDates; omit for annually.
addLines[].rampDeal.ramps[].quantity decimal yes Quantity for this ramp
addLines[].rampDeal.ramps[].listPrice decimal no Ramp list price. Defaults to the ramp unitPrice when omitted; must be omitted when the product line has enforceListPrice set.
addLines[].rampDeal.ramps[].unitPrice decimal yes Ramp unit price after discount
addLines[].rampDeal.ramps[].totalPrice decimal no Total price of this ramp period, stored as given. Required when externalizedCalculations is true; ignored otherwise.
addLines[].rampDeal.ramps[].invoiceFrequency any no Ramp invoice frequency. Must be allAtOnce on every ramp when invoiceTiming is allAtOnce. One of: "monthly", "biMonthly", "quarterly", "semiAnnually", "annually", "once", "custom", "template", "milestone", "allAtOnce".
addLines[].serviceStartDate date no Service start date of the added product (ISO 8601, YYYY-MM-DD). Defaults to the modificationDate.
addLines[].serviceEndDate date no Service end date of the added product (ISO 8601, YYYY-MM-DD). Defaults to coterminous with the subscription.
addLines[].externalIdentifiers array<object> no External identifiers to attach, e.g. from NetSuite or Salesforce
addLines[].externalIdentifiers[].fieldName string yes Field name defined in the corresponding ExternalIdentifierConfiguration
addLines[].externalIdentifiers[].value string yes External identifier value
addLines[].externalIdentifiers[].externalUrl string no Optional link to record in originating system
changeLines array<object> no Changes to existing subscription lines: quantity, price, discount, and tier changes. Every entry must carry at least one change field (CHANGE_LINE_NO_CHANGES). v1 implements quantity increases only: a decrease is rejected with QUANTITY_DECREASE_NOT_SUPPORTED (model a downgrade as a replaceGroup); tier/volume/stairstep and rate-card priced lines are supported, but flat-priced and usage-type lines are rejected with CHANGE_QUANTITY_UNSUPPORTED_LINE_TYPE. Price, discount, and tier changes (newUnitPrice, newListPrice, newDiscount, newDiscountType, newTiers) are reserved and rejected with CHANGE_KIND_NOT_SUPPORTED.
changeLines[].subscriptionLineId string yes Id of the subscription line being changed (a UUID)
changeLines[].newQuantity decimal no New total quantity for the line (not the delta). v1 supports increases only.
changeLines[].unitPrice decimal no Unit price for the added quantity when newQuantity is provided; defaults to the line's current unit price. This prices the delta only — use newUnitPrice to reprice the whole line.
changeLines[].totalPrice decimal no Total price of the added quantity, stored as given on the delta line. Required when externalizedCalculations is true, where the line must not be a ramp line; ignored otherwise.
changeLines[].newUnitPrice decimal no New unit price for the whole line from the modification date (reprice without quantity movement). Reserved: rejected with CHANGE_KIND_NOT_SUPPORTED until reprice ships.
changeLines[].newListPrice decimal no New list price for the whole line. Only valid together with newUnitPrice; must be omitted when the product line has enforceListPrice set. Reserved: rejected with CHANGE_KIND_NOT_SUPPORTED until reprice ships.
changeLines[].newDiscount decimal no New discount value for the line, interpreted based on newDiscountType. Reserved: rejected with CHANGE_KIND_NOT_SUPPORTED until reprice ships.
changeLines[].newDiscountType any no How newDiscount is interpreted (amount, percentage). Required when newDiscount is provided. One of: "amount", "percentage".
changeLines[].newTiers array<object> no Replacement tier table for a tier/volume/stairstep priced line; same shape and rules as addLines.tiers. May be combined with newQuantity. Reserved: rejected with CHANGE_KIND_NOT_SUPPORTED until reprice ships.
changeLines[].newTiers[].fromQuantity decimal yes Lower bound of quantity range (inclusive). First tier must start at 0.
changeLines[].newTiers[].toQuantity decimal no Upper bound of quantity range (inclusive). Omit on the last tier for open-ended ranges.
changeLines[].newTiers[].unitPrice decimal yes Per-unit price for quantities in this tier after discount
changeLines[].newTiers[].listPrice decimal no Per-unit list price before discount. Defaults to unitPrice.
changeLines[].newTiers[].priceModel any no Per-tier price model (flat, perUnit). Defaults to perUnit. One of: "flat", "perUnit".
cancelLines array<object> no Partial cancellations of existing subscription lines
cancelLines[].subscriptionLineId string yes Id of the subscription line to cancel (a UUID)
cancelLines[].serviceEndDate date no Service end date (ISO 8601, YYYY-MM-DD). Defaults to the modificationDate; in v1 a differing value is rejected (service always ends on the modificationDate).
replaceGroups array<object> no Product replacements (swaps/downgrades). Each group is atomic: its added lines activate together on the group's service start date and each replaced line's service ends on that same date. A group must contain at least one cancelLine and one addLine (REPLACE_GROUP_INCOMPLETE), all its addLines must resolve to the same service start date (REPLACE_GROUP_START_DATE_MISMATCH), and in v1 that date must be the modificationDate. A line may be canceled only once across cancelLines and all groups (DUPLICATE_CANCEL_TARGET).
replaceGroups[].cancelLines array<object> yes Existing subscription lines this group replaces. Their service ends on the group's service start date; no per-line serviceEndDate can be provided.
replaceGroups[].cancelLines[].subscriptionLineId string yes Id of the subscription line being replaced (a UUID)
replaceGroups[].addLines array<object> yes Replacement products to add. Same shape and pricing surface as top-level addLines. serviceStartDate defaults to the modificationDate and must resolve to the same date on every add in the group.
replaceGroups[].addLines[].productLineId string yes [fk: ProductLineApi.productLines.id] Id of the product line defining pricing and billing rules (a UUID)
replaceGroups[].addLines[].quantity decimal no Quantity of the product. Optional when (a) the line type sources quantity from usage records or external capture, or (b) rampDeal is provided (each ramp period carries its own quantity).
replaceGroups[].addLines[].invoiceFrequency any no Invoice frequency. Defaults to product line setting. One of: "monthly", "biMonthly", "quarterly", "semiAnnually", "annually", "once", "custom", "template", "milestone", "allAtOnce".
replaceGroups[].addLines[].invoiceTiming any no Invoice timing relative to service period (advance, arrears). Defaults to entity policy. One of: "advance", "arrears".
replaceGroups[].addLines[].lineInvoiceDay string no Specific day for generating invoices. Defaults to entity policy.
replaceGroups[].addLines[].priceModel any no Pricing model. Defaults to product line setting. One of: "flat", "perUnit", "tiered", "volume", "stairstep", "rateCard", "thresholdBased".
replaceGroups[].addLines[].unitOfMeasure any no Unit of measure (instance, gigabyte, terabyte, user, seat, minute, hour, day, month, each, license, activeUser, megabyte, message, text, platform, employee, personnel, credit, currency, package, case). Defaults to product line setting. One of: "instance", "gigabyte", "terabyte", "user", "seat", "minute", "hour", "day", "month", "each", "license", "activeUser", "megabyte", "message", "text", "platform", "employee", "personnel", "credit", "currency", "package", "case".
replaceGroups[].addLines[].listPrice decimal no Standard list price before discounts. Defaults to unitPrice when omitted; must be omitted when the product line has enforceListPrice set.
replaceGroups[].addLines[].unitPrice decimal no Actual unit price after applying discounts. Required unless rampDeal is provided.
replaceGroups[].addLines[].totalPrice decimal no Total price of the added line, stored as given. Required when externalizedCalculations is true; ignored otherwise.
replaceGroups[].addLines[].altProductName string no Alternative product name stored on the created sales order product. Passed through as given.
replaceGroups[].addLines[].discount decimal no Discount value (interpreted based on discountType)
replaceGroups[].addLines[].discountType any no Discount type (amount, percentage) One of: "amount", "percentage".
replaceGroups[].addLines[].pricingTerm any no Pricing term period. Defaults to product line setting. One of: "monthly", "biMonthly", "once", "quarterly", "semiAnnually", "annually".
replaceGroups[].addLines[].tiers array<object> no Pricing tiers for tiered/volume/stairstep price models. Tiers must cover contiguous quantity ranges starting at 0; bounds are inclusive and each tier's fromQuantity must be exactly the previous tier's toQuantity + 1 (e.g. 0-100, 101-500, 501-open).
replaceGroups[].addLines[].tiers[].fromQuantity decimal yes Lower bound of quantity range (inclusive). First tier must start at 0.
replaceGroups[].addLines[].tiers[].toQuantity decimal no Upper bound of quantity range (inclusive). Omit on the last tier for open-ended ranges.
replaceGroups[].addLines[].tiers[].unitPrice decimal yes Per-unit price for quantities in this tier after discount
replaceGroups[].addLines[].tiers[].listPrice decimal no Per-unit list price before discount. Defaults to unitPrice.
replaceGroups[].addLines[].tiers[].priceModel any no Per-tier price model (flat, perUnit). Defaults to perUnit. One of: "flat", "perUnit".
replaceGroups[].addLines[].rateCardEntries array<object> no Rate card entries for this product line. Required when priceModel is rateCard and the product line has no template entries.
replaceGroups[].addLines[].rateCardEntries[].identifier string yes BillableComponent identifier for this meter
replaceGroups[].addLines[].rateCardEntries[].description string no Free-text description of the rate card entry
replaceGroups[].addLines[].rateCardEntries[].unitOfMeasure string yes Unit of measure for this meter
replaceGroups[].addLines[].rateCardEntries[].unitPrice decimal yes Per-unit rate negotiated for this modification
replaceGroups[].addLines[].rateCardEntries[].listPrice decimal no Per-unit list price. Honored only when product line enforceListPrice is false.
replaceGroups[].addLines[].rateCardEntries[].conversion decimal no Conversion factor between billable and reporting units
replaceGroups[].addLines[].rampDeal object no Ramp deal definition for phased additions. Mutually exclusive with top-level quantity/unitPrice.
replaceGroups[].addLines[].rampDeal.interval any yes How ramps are defined. annually = auto-derive yearly ramps; specificDates = caller provides explicit serviceStartDate/serviceEndDate per ramp. One of: "annually", "specificDates".
replaceGroups[].addLines[].rampDeal.invoiceTiming any yes perInterval invoices at each ramp start; allAtOnce invoices the whole deal upfront and requires every ramp invoiceFrequency = allAtOnce. One of: "perInterval", "allAtOnce".
replaceGroups[].addLines[].rampDeal.ramps array<object> yes One entry per ramp, in chronological order. Minimum 2 ramps.
replaceGroups[].addLines[].rampDeal.ramps[].serviceStartDate date no Ramp service start date (ISO 8601, YYYY-MM-DD). Required for specificDates; omit for annually.
replaceGroups[].addLines[].rampDeal.ramps[].serviceEndDate date no Ramp service end date (ISO 8601, YYYY-MM-DD). Required for specificDates; omit for annually.
replaceGroups[].addLines[].rampDeal.ramps[].quantity decimal yes Quantity for this ramp
replaceGroups[].addLines[].rampDeal.ramps[].listPrice decimal no Ramp list price. Defaults to the ramp unitPrice when omitted; must be omitted when the product line has enforceListPrice set.
replaceGroups[].addLines[].rampDeal.ramps[].unitPrice decimal yes Ramp unit price after discount
replaceGroups[].addLines[].rampDeal.ramps[].totalPrice decimal no Total price of this ramp period, stored as given. Required when externalizedCalculations is true; ignored otherwise.
replaceGroups[].addLines[].rampDeal.ramps[].invoiceFrequency any no Ramp invoice frequency. Must be allAtOnce on every ramp when invoiceTiming is allAtOnce. One of: "monthly", "biMonthly", "quarterly", "semiAnnually", "annually", "once", "custom", "template", "milestone", "allAtOnce".
replaceGroups[].addLines[].serviceStartDate date no Service start date of the added product = the group's activation date (ISO 8601, YYYY-MM-DD). Defaults to the modificationDate.
replaceGroups[].addLines[].serviceEndDate date no Service end date of the added product (ISO 8601, YYYY-MM-DD). Defaults to coterminous with the subscription.
replaceGroups[].addLines[].externalIdentifiers array<object> no External identifiers to attach, e.g. from NetSuite or Salesforce
replaceGroups[].addLines[].externalIdentifiers[].fieldName string yes Field name defined in the corresponding ExternalIdentifierConfiguration
replaceGroups[].addLines[].externalIdentifiers[].value string yes External identifier value
replaceGroups[].addLines[].externalIdentifiers[].externalUrl string no Optional link to record in originating system
{
  "customerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "externalOrderId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "modificationType": "midTermModification",
  "bookDate": "2026-01-15",
  "effectiveDate": "2026-01-15",
  "oneTimeDiscountAmount": "19.99",
  "oneTimeDiscountAllocation": "firstInvoice",
  "billToAddressId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "soldToAddressId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "signDate": "2026-01-15",
  "purchaseOrder": "<purchaseOrder>",
  "opportunityId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "opportunityName": "<opportunityName>",
  "approvalStatus": "pendingApproval",
  "externalizedCalculations": true,
  "modificationDate": "2026-01-15",
  "term": 0,
  "priceChangePercentage": "19.99",
  "note": "<note>",
  "addLines": [
    {
      "productLineId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "quantity": "19.99",
      "invoiceFrequency": "monthly",
      "invoiceTiming": "advance",
      "lineInvoiceDay": "<lineInvoiceDay>",
      "priceModel": "flat",
      "unitOfMeasure": "instance",
      "listPrice": "19.99",
      "unitPrice": "19.99",
      "totalPrice": "19.99",
      "altProductName": "<altProductName>",
      "discount": "19.99",
      "discountType": "amount",
      "pricingTerm": "monthly",
      "tiers": [
        {
          "fromQuantity": "19.99",
          "toQuantity": "19.99",
          "unitPrice": "19.99",
          "listPrice": "19.99",
          "priceModel": "flat"
        }
      ],
      "rateCardEntries": [
        {
          "identifier": "<identifier>",
          "description": "<description>",
          "unitOfMeasure": "<unitOfMeasure>",
          "unitPrice": "19.99",
          "listPrice": "19.99",
          "conversion": "19.99"
        }
      ],
      "rampDeal": {
        "interval": "annually",
        "invoiceTiming": "perInterval",
        "ramps": [
          {
            "serviceStartDate": "2026-01-15",
            "serviceEndDate": "2026-01-15",
            "quantity": "19.99",
            "listPrice": "19.99",
            "unitPrice": "19.99",
            "totalPrice": "19.99",
            "invoiceFrequency": "monthly"
          }
        ]
      },
      "serviceStartDate": "2026-01-15",
      "serviceEndDate": "2026-01-15",
      "externalIdentifiers": [
        {
          "fieldName": "<fieldName>",
          "value": "<value>",
          "externalUrl": "<externalUrl>"
        }
      ]
    }
  ],
  "changeLines": [
    {
      "subscriptionLineId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "newQuantity": "19.99",
      "unitPrice": "19.99",
      "totalPrice": "19.99",
      "newUnitPrice": "19.99",
      "newListPrice": "19.99",
      "newDiscount": "19.99",
      "newDiscountType": "amount",
      "newTiers": [
        {
          "fromQuantity": "19.99",
          "toQuantity": "19.99",
          "unitPrice": "19.99",
          "listPrice": "19.99",
          "priceModel": "flat"
        }
      ]
    }
  ],
  "cancelLines": [
    {
      "subscriptionLineId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "serviceEndDate": "2026-01-15"
    }
  ],
  "replaceGroups": [
    {
      "cancelLines": [
        {
          "subscriptionLineId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
        }
      ],
      "addLines": [
        {
          "productLineId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
          "quantity": "19.99",
          "invoiceFrequency": "monthly",
          "invoiceTiming": "advance",
          "lineInvoiceDay": "<lineInvoiceDay>",
          "priceModel": "flat",
          "unitOfMeasure": "instance",
          "listPrice": "19.99",
          "unitPrice": "19.99",
          "totalPrice": "19.99",
          "altProductName": "<altProductName>",
          "discount": "19.99",
          "discountType": "amount",
          "pricingTerm": "monthly",
          "tiers": [
            {
              "fromQuantity": null,
              "toQuantity": null,
              "unitPrice": null,
              "listPrice": null,
              "priceModel": null
            }
          ],
          "rateCardEntries": [
            {
              "identifier": null,
              "description": null,
              "unitOfMeasure": null,
              "unitPrice": null,
              "listPrice": null,
              "conversion": null
            }
          ],
          "rampDeal": {
            "interval": "annually",
            "invoiceTiming": "perInterval",
            "ramps": [
              null
            ]
          },
          "serviceStartDate": "2026-01-15",
          "serviceEndDate": "2026-01-15",
          "externalIdentifiers": [
            {
              "fieldName": null,
              "value": null,
              "externalUrl": null
            }
          ]
        }
      ]
    }
  ]
}

Response

200 Success

Under data (modifySubscriptionOutput):

Field Type Required Description
salesOrderId string no Id of the generated sales order (a UUID). Absent when a midTermModification payload contains only cancellations (no sales order is created).
subscriptionModificationId string no Id of the created SubscriptionModification record (a UUID). Absent for renewal (a renewal creates no SubscriptionModification).
approvalStatus string yes Approval status of the result (pendingApproval, approved)
serviceStartDate date no renew and earlyRenew only: service start date of the new term (the day after the current service end date for renew, the modificationDate for earlyRenew)
serviceEndDate date no renew and earlyRenew only: service end date of the new term
term number no renew and earlyRenew only: renewal term in months that was applied
{
  "data": {
    "salesOrderId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "subscriptionModificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "approvalStatus": "<approvalStatus>",
    "serviceStartDate": "2026-01-15",
    "serviceEndDate": "2026-01-15",
    "term": 0
  },
  "diagnostics": [
    {
      "code": "<code>",
      "message": "<message>",
      "severity": "error",
      "path": [
        "<path>"
      ],
      "details": "<details>"
    }
  ]
}

Response headers

Errors

Code Status
SUBSCRIPTION_NOT_FOUND 400
SUBSCRIPTION_LINE_NOT_FOUND 400
MODIFICATION_DATE_OUTSIDE_SERVICE_PERIOD 400
QUANTITY_DECREASE_NOT_SUPPORTED 400
CHANGE_QUANTITY_UNSUPPORTED_LINE_TYPE 400
CHANGE_LINE_NO_CHANGES 400
REPLACED_LINE_NOT_ACTIVE 400
REPLACE_GROUP_INCOMPLETE 400
REPLACE_GROUP_START_DATE_MISMATCH 400
DUPLICATE_EXTERNAL_ORDER_ID 400
DUPLICATE_CANCEL_TARGET 400
SUBSCRIPTION_NOT_RENEWABLE 400
EARLY_RENEWAL_DATE_INVALID 400
SUBSCRIPTION_NOT_EARLY_RENEWABLE 400
EARLY_RENEWAL_ALREADY_PENDING 400
CHANGE_KIND_NOT_SUPPORTED 400
RENEWAL_TERM_MISSING 400
RENEWAL_ALREADY_PENDING 400
NOTHING_TO_MODIFY 400
SUBSCRIPTION_LINE_NOT_ACTIVE 400
MODIFICATION_DATE_REQUIRED 400
UNSUPPORTED_FIELDS 400
PRICE_CHANGE_PERCENTAGE_NEGATIVE 400
VALIDATION_FAILED 400
REPLACE_GROUP_RAMP_NOT_SUPPORTED 400
TOTAL_PRICE_REQUIRED 400
CHANGE_LINE_TOTAL_PRICE_REQUIRED 400
EXTERNALIZED_RAMP_CHANGE_NOT_SUPPORTED 400
IDEMPOTENCY_KEY_CONFLICT 409
IDEMPOTENCY_PAYLOAD_MISMATCH 422

Statuses