Guides and Examples
...
Orders
Creating Draft Change Orders
40 min
this guide provides comprehensive instructions for creating draft change orders using the nue lifecycle management api learn how to modify existing subscriptions through quantity updates, renewals, upgrades, downgrades, and other subscription lifecycle changes prerequisites before you begin, ensure you have a valid nue api key with change order permissions asset numbers (sub xxxxxx format) for existing subscriptions to modify understanding of subscription change types and their implications basic knowledge of rest apis and json customer timezone information for accurate date calculations authentication all change order operations require authentication using your nue api key in the nue api key header const myheaders = new headers(); myheaders append("nue api key", "your api key here"); myheaders append("content type", "application/json"); change order overview change orders modify existing subscriptions through the /change orders endpoint unlike regular orders that create new subscriptions, change orders reference existing assets and apply specific change types try it now create change order → https //api docs nue io/create change order important limitations ⚠️ draft change orders have specific limitations compared to regular draft orders no description fields change orders do not support description fields at any level no price tag support change orders do not accept pricetagids or pricetagcodes fields asset based structure changes are applied to existing assets, not new product configurations limited customization only change type specific parameters are supported these limitations ensure change orders maintain data integrity when modifying existing subscriptions change types reference the nue api supports 10 different change types change type purpose required fields use case updatequantity change subscription quantity quantity , startdate scale subscription up/down updateterm modify subscription term term extend/shorten contract renew renew expiring subscription renewalterm continue subscription coterm align with another subscription cotermdate synchronize end dates cancel terminate subscription cancellationdate end subscription early convertfreetrial convert trial to paid startdate , term monetize trial users upgrade move to higher tier product targetpricebookentryid , startdate increase service level downgrade move to lower tier product targetpricebookentryid , startdate reduce service level swap switch to different product targetpricebookentryid , startdate change product type reconfigure add bundle add ons startdate , addons self service bundle management basic change order structure all change orders follow this base structure const changeorderrequest = { // optional configuration options options { previewinvoice true, // generate billing preview (default true) calculatetax false // calculate tax amounts (default false) }, // optional timezone for date calculations timezone "america/new york", // required array of asset changes assetchanges \[ { changetype "updatequantity", // required change type assetnumber "sub 000001", // required asset to modify // additional fields based on change type } ] }; request body schema required fields field type description example assetchanges array list of asset changes to apply see asset change schema below optional fields field type description example options previewinvoice boolean generate billing preview (default true) true options calculatetax boolean calculate tax amounts (default false) false timezone string customer timezone for calculations "america/new york" asset change schema field type required description changetype string yes type of change (see enum above) assetnumber string yes asset identifier (sub xxxxxx format) change type specific fields updatequantity quantity (number, required) new quantity startdate (string, required) change start date updateterm term (number, required) new term in months renew renewalterm (number, required) renewal term in months coterm cotermdate (string, required) target coterm date cancel cancellationdate (string, required) cancellation date convertfreetrial startdate (string, required) conversion start date term (number, required) subscription term in months overridetrialend (boolean, optional) override trial end behavior upgrade/downgrade/swap targetpricebookentryid (string, required) target product id startdate (string, required) change start date samepriceswap (boolean, optional, swap only) same price swap flag reconfigure startdate (string, required) change start date addons (array, required) array of add on configurations productoptionid (string, required) product option id for bundle add on reconfigureeffectivedate (string, required) when add on change takes effect productoptionquantity (number, required) quantity of the add on ⚠️ important restriction reconfigure change orders cannot be combined with other change types in a single transaction advanced change order scenarios update subscription quantity scale an existing subscription up or down const myheaders = new headers(); myheaders append("nue api key", "your api key here"); myheaders append("content type", "application/json"); const quantitychangeorder = { timezone "america/new york", assetchanges \[ { changetype "updatequantity", assetnumber "sub 000293", quantity 150, startdate "2025 02 01" } ], options { previewinvoice true, calculatetax true } }; fetch('https //api nue io/change orders', { method 'post', headers myheaders, body json stringify(quantitychangeorder) }) then(response => response json()) then(result => { if (result status === 'success') { console log('✅ quantity change order created successfully'); console log('change order id ', result data order? id); } }) catch(error => console log('quantity change failed ', error)); update subscription term modify the term length of an existing subscription const myheaders = new headers(); myheaders append("nue api key", "your api key here"); myheaders append("content type", "application/json"); const termupdateorder = { timezone "america/new york", assetchanges \[ { changetype "updateterm", assetnumber "sub 000293", term 24 } ], options { previewinvoice true, calculatetax true } }; fetch('https //api nue io/change orders', { method 'post', headers myheaders, body json stringify(termupdateorder) }) then(response => response json()) then(result => { if (result status === 'success') { console log('✅ term update order created successfully'); console log('change order id ', result data order? id); } }) catch(error => console log('term update failed ', error)); renew subscription extend an expiring subscription const renewalorder = { timezone "america/new york", assetchanges \[ { changetype "renew", assetnumber "sub 000293", renewalterm 12 } ], options { previewinvoice true, calculatetax true } }; fetch('https //api nue io/change orders', { method 'post', headers myheaders, body json stringify(renewalorder) }) then(response => response json()) then(result => { if (result status === 'success') { console log('✅ renewal order created successfully'); } }) catch(error => console log('renewal failed ', error)); convert free trial to paid subscription monetize trial users by converting to paid plans const trialconversionorder = { timezone "america/new york", assetchanges \[ { changetype "convertfreetrial", assetnumber "sub 000293", startdate "2025 03 21", term 12, overridetrialend false } ], options { previewinvoice true, calculatetax true } }; fetch('https //api nue io/change orders', { method 'post', headers myheaders, body json stringify(trialconversionorder) }) then(response => response json()) then(result => { if (result status === 'success') { console log('✅ trial conversion successful'); } }) catch(error => console log('trial conversion failed ', error)); upgrade subscription move customer to a higher tier product const upgradeorder = { timezone "america/new york", assetchanges \[ { changetype "upgrade", assetnumber "sub 000293", targetpricebookentryid "01u4x000005yw0baas", startdate "2025 03 21" } ], options { previewinvoice true, calculatetax true } }; fetch('https //api nue io/change orders', { method 'post', headers myheaders, body json stringify(upgradeorder) }) then(response => response json()) then(result => { if (result status === 'success') { console log('✅ upgrade order created successfully'); } }) catch(error => console log('upgrade failed ', error)); downgrade subscription move customer to a lower tier product const downgradeorder = { timezone "america/new york", assetchanges \[ { changetype "downgrade", assetnumber "sub 000293", targetpricebookentryid "01u4x000005yw0caas", startdate "2025 03 21" } ], options { previewinvoice true, calculatetax false } }; fetch('https //api nue io/change orders', { method 'post', headers myheaders, body json stringify(downgradeorder) }) then(response => response json()) then(result => { if (result status === 'success') { console log('✅ downgrade order created successfully'); } }) catch(error => console log('downgrade failed ', error)); co terminate multiple subscriptions align subscription end dates for easier management const cotermorder = { timezone "america/new york", assetchanges \[ { changetype "coterm", assetnumber "sub 000293", cotermdate "2025 07 20" } ], options { previewinvoice true, calculatetax true } }; fetch('https //api nue io/change orders', { method 'post', headers myheaders, body json stringify(cotermorder) }) then(response => response json()) then(result => { if (result status === 'success') { console log('✅ co termination order created'); } }) catch(error => console log('co termination failed ', error)); cancel subscription terminate a subscription with proper notice const cancellationorder = { timezone "america/new york", assetchanges \[ { changetype "cancel", assetnumber "sub 000293", cancellationdate "2025 03 21" } ], options { previewinvoice true, calculatetax true } }; fetch('https //api nue io/change orders', { method 'post', headers myheaders, body json stringify(cancellationorder) }) then(response => response json()) then(result => { if (result status === 'success') { console log('✅ cancellation order created'); } }) catch(error => console log('cancellation failed ', error)); reconfigure bundle subscription add product options (add ons) from existing bundle subscriptions const myheaders = new headers(); myheaders append("nue api key", "your api key here"); myheaders append("content type", "application/json"); const reconfigureorder = { timezone "america/new york", assetchanges \[ { changetype "reconfigure", assetnumber "sub 000050", startdate "2025 08 26", addons \[ { productoptionid "a0g7z000007guxuaam", reconfigureeffectivedate "2025 08 26", productoptionquantity 2 } ] } ], options { previewinvoice true, calculatetax true } }; fetch('https //api nue io/change orders', { method 'post', headers myheaders, body json stringify(reconfigureorder) }) then(response => response json()) then(result => { if (result status === 'success') { console log('✅ bundle reconfiguration successful'); console log('change order id ', result data order? id); } }) catch(error => console log('bundle reconfiguration failed ', error)); product swap switch to a different product at the same level const swaporder = { timezone "america/new york", assetchanges \[ { changetype "swap", assetnumber "sub 000293", targetpricebookentryid "01u4x000005yw0daas", startdate "2025 03 21", samepriceswap false } ], options { previewinvoice true, calculatetax true } }; fetch('https //api nue io/change orders', { method 'post', headers myheaders, body json stringify(swaporder) }) then(response => response json()) then(result => { if (result status === 'success') { console log('✅ product swap order created'); } }) catch(error => console log('product swap failed ', error)); multiple changes in single order apply multiple changes across different subscriptions const multichangeorder = { timezone "america/new york", assetchanges \[ { changetype "updatequantity", assetnumber "sub 000001", quantity 200, startdate "2025 07 01" }, { changetype "upgrade", assetnumber "sub 000002", targetpricebookentryid "pbe premium addon", startdate "2025 07 01" }, { changetype "cancel", assetnumber "sub 000003", cancellationdate "2025 07 31" } ], options { previewinvoice true, calculatetax true } }; fetch('https //api nue io/change orders', { method 'post', headers myheaders, body json stringify(multichangeorder) }) then(response => response json()) then(result => { if (result status === 'success') { console log('✅ multiple changes applied successfully'); } }) catch(error => console log('multiple changes failed ', error)); change order service class implement a comprehensive service for change order management class changeorderservice { constructor(apikey) { this apikey = apikey; this headers = new headers(); this headers append("nue api key", apikey); this headers append("content type", "application/json"); } async createchangeorder(changeorderinput) { try { // step 1 validate change order data const validatedorder = this validatechangeorderdata(changeorderinput); // step 2 apply business rules and defaults const enrichedorder = this enrichchangeorderdata(validatedorder); // step 3 submit change order const changeorder = await this submitchangeorder(enrichedorder); // step 4 process results const processedresult = this processchangeorderresult(changeorder); return { success true, order processedresult order, assets processedresult assets, previews processedresult previews, warnings processedresult warnings, summary this generatechangeordersummary(processedresult) }; } catch (error) { console error('change order creation failed ', error); return { success false, error error message, orderinput changeorderinput }; } } validatechangeorderdata(orderinput) { const errors = \[]; // required field validation if (!orderinput timezone) { errors push('time zone is required for change orders'); } if (!orderinput assetchanges || orderinput assetchanges length === 0) { errors push('at least one asset change is required'); } // asset change validation orderinput assetchanges? foreach((change, index) => { const changepath = `asset change ${index + 1}`; if (!change changetype) { errors push(`${changepath} change type is required`); } if (!change assetnumber) { errors push(`${changepath} asset number is required`); } // validate asset number format if (change assetnumber && !change assetnumber match(/^sub \d{6}$/)) { errors push(`${changepath} asset number must be in format sub xxxxxx`); } // change type specific validation this validatechangetyperequirements(change, changepath, errors); }); if (errors length > 0) { throw new error(`change order validation failed \n${errors join('\n')}`); } return orderinput; } validatechangetyperequirements(change, changepath, errors) { const changetype = change changetype; switch (changetype) { case 'updatequantity' if (!change quantity || change quantity <= 0) { errors push(`${changepath} quantity must be greater than 0 for updatequantity`); } if (!change startdate) { errors push(`${changepath} start date is required for updatequantity`); } break; case 'updateterm' if (!change term || change term <= 0) { errors push(`${changepath} term must be greater than 0 for updateterm`); } break; case 'renew' if (!change renewalterm || change renewalterm <= 0) { errors push(`${changepath} renewal term must be greater than 0 for renew`); } break; case 'coterm' if (!change cotermdate) { errors push(`${changepath} co term date is required for coterm`); } break; case 'cancel' if (!change cancellationdate) { errors push(`${changepath} cancellation date is required for cancel`); } break; case 'convertfreetrial' if (!change startdate) { errors push(`${changepath} start date is required for convertfreetrial`); } if (!change term || change term <= 0) { errors push(`${changepath} term must be greater than 0 for convertfreetrial`); } break; case 'upgrade' case 'downgrade' case 'swap' if (!change targetpricebookentryid) { errors push(`${changepath} target price book entry id is required for ${changetype}`); } if (!change startdate) { errors push(`${changepath} start date is required for ${changetype}`); } break; case 'reconfigure' if (!change startdate) { errors push(`${changepath} start date is required for reconfigure`); } if (!change addons || !array isarray(change addons) || change addons length === 0) { errors push(`${changepath} at least one add on is required for reconfigure`); } else { change addons foreach((addon, addonindex) => { const addonpath = `${changepath} add on ${addonindex + 1}`; if (!addon productoptionid) { errors push(`${addonpath} product option id is required`); } if (!addon reconfigureeffectivedate) { errors push(`${addonpath} reconfigure effective date is required`); } if (!addon productoptionquantity || addon productoptionquantity <= 0) { errors push(`${addonpath} product option quantity must be greater than 0`); } }); } break; default errors push(`${changepath} invalid change type ${changetype}`); } } enrichchangeorderdata(orderinput) { return { orderinput, // set default options if not provided options { previewinvoice true, calculatetax false, orderinput options } }; } async submitchangeorder(orderdata) { const response = await fetch('https //api nue io/change orders', { method 'post', headers this headers, body json stringify(orderdata) }); if (!response ok) { const errortext = await response text(); throw new error(`api error ${response status} ${errortext}`); } const result = await response json(); if (result status !== 'success') { throw new error(`change order creation failed ${result message || 'unknown error'}`); } return result; } processchangeorderresult(apiresult) { return { order apiresult data order, assets apiresult data assets || \[], previews apiresult data previews || \[], warnings apiresult data warnings || \[] }; } generatechangeordersummary(result) { const order = result order; const assets = result assets; // group changes by type const changetypes = assets reduce((acc, asset) => { const type = asset changetype || 'unknown'; acc\[type] = (acc\[type] || 0) + 1; return acc; }, {}); // calculate billing impact const totalbillingimpact = result previews reduce((sum, preview) => { return sum + (preview\ netamount || 0); }, 0); return { orderid order id, effectivedate order effectivedate, totalchanges assets length, changetypes changetypes, billingimpact totalbillingimpact, haswarnings result warnings length > 0, warningcount result warnings length }; } } // usage example const changeorderservice = new changeorderservice("your api key here"); const subscriptionupgrade = { timezone "america/new york", assetchanges \[ { changetype "upgrade", assetnumber "sub 000001", targetpricebookentryid "pbe enterprise annual", startdate "2025 08 01" } ] }; changeorderservice createchangeorder(subscriptionupgrade) then(result => { if (result success) { console log('\n🎉 change order created successfully!'); console log(`order id ${result summary orderid}`); console log(`changes applied ${result summary totalchanges}`); console log(`billing impact ${result summary billingimpact >= 0 ? '+' ''}$${result summary billingimpact}`); if (result summary haswarnings) { console log(`\n⚠️ ${result summary warningcount} warnings to review`); } } else { console error('❌ change order failed ', result error); } }); request body schema required fields field type description example assetchanges array list of asset changes to apply see asset change schema below asset change schema field type required description changetype string yes type of change (see enum above) assetnumber string yes asset identifier (sub xxxxxx format) change type specific fields updatequantity quantity (number, required) new quantity startdate (string, required) change start date updateterm term (number, required) new term in months renew renewalterm (number, required) renewal term in months upgrade/downgrade/swap targetpricebookentryid (string, required) target product id startdate (string, required) change start date samepriceswap (boolean, optional, swap only) same price swap flag reconfigure startdate (string, required) change start date addons (array, required) array of add on configurations productoptionid (string, required) product option id for bundle add on reconfigureeffectivedate (string, required) when add on change takes effect productoptionquantity (number, required) quantity of the add on response structure success response (201 created) { "status" "success", "data" { "order" { "id" "change order uuid", "effectivedate" "2025 01 01" }, "assets" \[ { "id" "asset uuid", "assetnumber" "sub 000001", "changetype" "updatequantity", "quantity" 150, "startdate" "2025 01 01", "enddate" "2025 12 31", "status" "draft" } ], "previews" \[ { "assetnumber" "sub 000001", "proratedamount" 2500 00, "nextinvoiceadjustment" 1000 00, "netamount" 3500 00 } ], "warnings" \[] } } error handling common change order errors error code description resolution asset not found asset number doesn't exist verify asset number format and existence invalid change type change type not supported for asset check asset type compatibility change not allowed change violates business rules review asset status and constraints insufficient permissions user lacks change permissions verify api key permissions invalid target product target product not available check product catalog availability handle change specific errors try { const result = await changeorderservice createchangeorder(changeorder); } catch (error) { if (error message includes('asset not found')) { console error('asset error subscription not found check asset number'); } else if (error message includes('change not allowed')) { console error('business rule error change not permitted for this subscription'); } else if (error message includes('invalid target product')) { console error('product error target product not available for this customer'); } } best practices change order design validate asset existence before creating change orders use appropriate change types based on business intent consider billing impact with preview invoices timing and scheduling plan effective dates considering billing cycles coordinate multiple changes for optimal customer experience respect minimum notice periods for cancellations align with customer timezone for accurate calculations business operations implement approval workflows for significant changes monitor change order patterns for customer health insights automate common changes like renewals and quantity adjustments maintain change history for customer relationship management this comprehensive guide enables you to efficiently manage subscription lifecycles through the nue change orders api, supporting all types of subscription modifications from simple quantity updates to complex product transitions