Updating Subscriptions
This guide provides comprehensive instructions for updating subscription data using the Nue Lifecycle Management API. Learn how to modify subscription settings, manage auto-renewal configurations, update custom fields, and implement efficient subscription management workflows.
Prerequisites
Before you begin, ensure you have:
- A valid Nue API key with subscription update permissions
- Subscription IDs for the subscriptions you want to update
- Understanding of subscription data model and updateable fields
- Basic knowledge of REST APIs and JSON
- Familiarity with subscription lifecycle and business rules
Authentication
All subscription update 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");Basic Subscription Updates
Update Auto-Renewal Setting
Try it now: Update Subscription →
const myHeaders = new Headers();
myHeaders.append("nue-api-key", "YOUR_API_KEY_HERE");
myHeaders.append("Content-Type", "application/json");
// Update subscription auto-renewal setting
const subscriptionId = "subscription-123e4567-e89b-12d3-a456-426614174000";
const updateData = {
autoRenew: false // Disable auto-renewal
};
fetch(`https://api.nue.io/subscriptions/${subscriptionId}`, {
method: 'PATCH',
headers: myHeaders,
body: JSON.stringify(updateData)
})
.then(response => response.json())
.then(result => {
console.log('Subscription updated successfully:', result);
if (result.status === 'SUCCESS' && result.data.length > 0) {
const subscription = result.data[0];
console.log('\n✅ Subscription Update Completed');
console.log(`Subscription ID: ${subscription.id}`);
console.log(`Name: ${subscription.name}`);
console.log(`Auto Renew: ${subscription.autoRenew}`);
console.log(`Status: ${subscription.status}`);
console.log(`Last Modified: ${subscription.lastModifiedDate}`);
console.log(`Modified By: ${subscription.lastModifiedById}`);
// Display renewal implications
if (!subscription.autoRenew) {
console.log('\n⚠️ Auto-renewal disabled - manual renewal required');
console.log(`Subscription expires: ${subscription.subscriptionEndDate}`);
} else {
console.log('\n🔄 Auto-renewal enabled');
console.log(`Next renewal: ${subscription.subscriptionEndDate}`);
}
}
})
.catch(error => console.log('Error:', error));Update Custom Fields
Update custom fields on subscription records:
// Update custom field data
const customFieldUpdate = {
Ruby__Custom_Field__c: "Updated Custom Value", // Example custom field
autoRenew: true // Can combine with standard field updates
};
fetch(`https://api.nue.io/subscriptions/${subscriptionId}`, {
method: 'PATCH',
headers: myHeaders,
body: JSON.stringify(customFieldUpdate)
})
.then(response => response.json())
.then(result => {
if (result.status === 'SUCCESS') {
const subscription = result.data[0];
console.log('✅ Custom Field Updated Successfully');
console.log(`Subscription: ${subscription.name}`);
console.log(`Custom Field Value: ${subscription.Ruby__Custom_Field__c}`);
console.log(`Auto Renew: ${subscription.autoRenew}`);
console.log(`Last Modified: ${subscription.lastModifiedDate}`);
// Track the update for audit purposes
logSubscriptionUpdate(subscription.id, customFieldUpdate, 'custom_field_update');
}
})
.catch(error => console.log('Custom field update failed:', error));
function logSubscriptionUpdate(subscriptionId, updateData, updateType) {
const auditLog = {
subscriptionId,
updateType,
updatedFields: Object.keys(updateData),
timestamp: new Date().toISOString(),
updateData
};
console.log('📊 Update logged for audit:', auditLog);
// In production, send to your audit/logging system
}Advanced Subscription Update Workflows
Subscription Update Service
Implement a comprehensive service for subscription management with validation and business rules:
class SubscriptionUpdateService {
constructor(apiKey) {
this.apiKey = apiKey;
this.headers = new Headers();
this.headers.append("nue-api-key", apiKey);
this.headers.append("Content-Type", "application/json");
// Track updates for audit and rollback purposes
this.updateHistory = new Map();
}
async updateSubscription(subscriptionId, updateData, options = {}) {
try {
// Step 1: Validate update data and business rules
if (options.validate) {
await this.validateUpdate(subscriptionId, updateData);
}
// Step 2: Get current subscription state for rollback
const currentState = await this.getCurrentSubscriptionState(subscriptionId);
// Step 3: Apply business rules and transformations
const processedUpdate = this.processUpdateData(updateData, currentState, options);
// Step 4: Submit the update
const result = await this.submitUpdate(subscriptionId, processedUpdate);
// Step 5: Track the update
this.trackUpdate(subscriptionId, processedUpdate, result, currentState);
// Step 6: Handle post-update tasks
if (options.enableNotifications) {
await this.handlePostUpdateTasks(result.data[0], processedUpdate);
}
return {
success: true,
subscriptionId,
updatedSubscription: result.data[0],
appliedChanges: processedUpdate,
previousState: currentState
};
} catch (error) {
console.error(`Subscription update failed for ${subscriptionId}:`, error);
return {
success: false,
subscriptionId,
error: error.message,
updateData
};
}
}
async validateUpdate(subscriptionId, updateData) {
const errors = [];
// Validate updateable fields
const allowedFields = ['autoRenew'];
const customFieldPattern = /^[A-Za-z0-9_]+__[A-Za-z0-9_]+__c$/;
Object.keys(updateData).forEach(field => {
if (!allowedFields.includes(field) && !customFieldPattern.test(field)) {
errors.push(`Field '${field}' is not updateable or invalid custom field format`);
}
});
// Validate autoRenew field specifically
if (updateData.hasOwnProperty('autoRenew') && typeof updateData.autoRenew !== 'boolean') {
errors.push('autoRenew must be a boolean value');
}
// Business rule validations
if (updateData.autoRenew === false) {
// Check if subscription is close to expiry
const subscription = await this.getCurrentSubscriptionState(subscriptionId);
const endDate = new Date(subscription.subscriptionEndDate);
const now = new Date();
const daysToExpiry = Math.ceil((endDate - now) / (1000 * 60 * 60 * 24));
if (daysToExpiry <= 30) {
errors.push(`Warning: Disabling auto-renewal for subscription expiring in ${daysToExpiry} days`);
}
}
if (errors.length > 0) {
throw new Error(`Validation failed:\n${errors.join('\n')}`);
}
}
async getCurrentSubscriptionState(subscriptionId) {
// In a real implementation, you would fetch the current subscription
// For this example, we'll simulate the response
console.log(`Fetching current state for subscription ${subscriptionId}...`);
// This would be a call to GET /subscriptions with a filter
// For demo purposes, returning mock data
return {
id: subscriptionId,
name: "Mock Subscription",
autoRenew: true,
status: "active",
subscriptionEndDate: "2025-12-31",
totalAmount: 120000
};
}
processUpdateData(updateData, currentState, options) {
const processed = { ...updateData };
// Apply business logic transformations
if (processed.autoRenew !== undefined) {
// Log renewal setting changes
if (processed.autoRenew !== currentState.autoRenew) {
console.log(`🔄 Auto-renewal changing: ${currentState.autoRenew} → ${processed.autoRenew}`);
// Add metadata for audit trail
if (options.updateReason) {
processed.updateReason = options.updateReason;
}
}
}
// Handle custom field updates
Object.keys(processed).forEach(field => {
if (field.includes('__c')) {
console.log(`🏷️ Custom field update: ${field} = ${processed[field]}`);
}
});
return processed;
}
async submitUpdate(subscriptionId, updateData) {
const response = await fetch(`https://api.nue.io/subscriptions/${subscriptionId}`, {
method: 'PATCH',
headers: this.headers,
body: JSON.stringify(updateData)
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Update failed: ${response.status} ${errorText}`);
}
const result = await response.json();
if (result.status !== 'SUCCESS') {
throw new Error(`Update failed: ${result.message || 'Unknown error'}`);
}
return result;
}
trackUpdate(subscriptionId, updateData, result, previousState) {
const updateRecord = {
subscriptionId,
timestamp: new Date().toISOString(),
updateData,
previousState,
newState: result.data[0],
success: true
};
this.updateHistory.set(`${subscriptionId}_${Date.now()}`, updateRecord);
console.log(`📊 Update tracked for subscription ${subscriptionId}`);
}
async handlePostUpdateTasks(updatedSubscription, appliedChanges) {
// Post-update notification and business logic
// 1. Send notifications if auto-renewal changed
if (appliedChanges.hasOwnProperty('autoRenew')) {
await this.sendAutoRenewalNotification(updatedSubscription, appliedChanges.autoRenew);
}
// 2. Update related systems
await this.updateRelatedSystems(updatedSubscription, appliedChanges);
// 3. Schedule follow-up tasks
await this.scheduleFollowUpTasks(updatedSubscription, appliedChanges);
}
async sendAutoRenewalNotification(subscription, newAutoRenewSetting) {
console.log(`📧 Sending auto-renewal notification...`);
const notification = {
subscriptionId: subscription.id,
subscriptionName: subscription.name,
customerId: subscription.customerId,
autoRenewEnabled: newAutoRenewSetting,
subscriptionEndDate: subscription.subscriptionEndDate,
notificationType: 'auto_renewal_change'
};
if (newAutoRenewSetting) {
console.log('✅ Auto-renewal enabled - customer will be billed automatically');
} else {
console.log('⚠️ Auto-renewal disabled - manual renewal required');
// Schedule renewal reminder
const endDate = new Date(subscription.subscriptionEndDate);
const reminderDate = new Date(endDate.getTime() - 30 * 24 * 60 * 60 * 1000);
notification.reminderScheduled = reminderDate.toISOString();
console.log(`📅 Renewal reminder scheduled for ${reminderDate.toLocaleDateString()}`);
}
// In production, integrate with your notification system
console.log('📧 Notification queued:', notification);
}
async updateRelatedSystems(subscription, changes) {
console.log(`🔗 Updating related systems for subscription ${subscription.id}...`);
// Examples of related system updates:
// - CRM system updates
// - Billing system notifications
// - Customer portal updates
// - Analytics/reporting systems
const systemUpdates = [];
if (changes.autoRenew !== undefined) {
systemUpdates.push({
system: 'billing',
action: 'update_auto_renewal',
subscriptionId: subscription.id,
autoRenew: changes.autoRenew
});
systemUpdates.push({
system: 'crm',
action: 'update_renewal_flag',
subscriptionId: subscription.id,
autoRenew: changes.autoRenew
});
}
// Custom field updates might need to sync to external systems
Object.keys(changes).forEach(field => {
if (field.includes('__c')) {
systemUpdates.push({
system: 'data_warehouse',
action: 'sync_custom_field',
subscriptionId: subscription.id,
field: field,
value: changes[field]
});
}
});
console.log(`📊 ${systemUpdates.length} system updates queued:`, systemUpdates);
}
async scheduleFollowUpTasks(subscription, changes) {
console.log(`📅 Scheduling follow-up tasks for subscription ${subscription.id}...`);
const tasks = [];
// If auto-renewal was disabled, schedule renewal outreach
if (changes.autoRenew === false) {
const endDate = new Date(subscription.subscriptionEndDate);
const outreachDate = new Date(endDate.getTime() - 45 * 24 * 60 * 60 * 1000);
tasks.push({
type: 'renewal_outreach',
subscriptionId: subscription.id,
scheduledDate: outreachDate.toISOString(),
priority: 'high',
assignee: 'account_manager'
});
}
// If auto-renewal was enabled, schedule renewal confirmation
if (changes.autoRenew === true) {
const endDate = new Date(subscription.subscriptionEndDate);
const confirmationDate = new Date(endDate.getTime() - 7 * 24 * 60 * 60 * 1000);
tasks.push({
type: 'renewal_confirmation',
subscriptionId: subscription.id,
scheduledDate: confirmationDate.toISOString(),
priority: 'medium',
assignee: 'customer_success'
});
}
console.log(`📋 ${tasks.length} follow-up tasks scheduled:`, tasks);
}
async bulkUpdateSubscriptions(subscriptionUpdates, options = {}) {
console.log(`🚀 Starting bulk update for ${subscriptionUpdates.length} subscriptions...`);
const results = {
successful: [],
failed: [],
summary: {}
};
// Process in batches to respect rate limits
const batchSize = options.batchSize || 5;
for (let i = 0; i < subscriptionUpdates.length; i += batchSize) {
const batch = subscriptionUpdates.slice(i, i + batchSize);
console.log(`Processing batch ${Math.floor(i/batchSize) + 1}/${Math.ceil(subscriptionUpdates.length/batchSize)}`);
const batchPromises = batch.map(update =>
this.updateSubscription(update.subscriptionId, update.updateData, update.options || options)
);
const batchResults = await Promise.allSettled(batchPromises);
batchResults.forEach((result, index) => {
const update = batch[index];
if (result.status === 'fulfilled' && result.value.success) {
results.successful.push(result.value);
} else {
const error = result.status === 'rejected' ? result.reason.message : result.value.error;
results.failed.push({
subscriptionId: update.subscriptionId,
updateData: update.updateData,
error
});
}
});
// Brief pause between batches
if (i + batchSize < subscriptionUpdates.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
// Generate summary
results.summary = {
total: subscriptionUpdates.length,
successful: results.successful.length,
failed: results.failed.length,
successRate: ((results.successful.length / subscriptionUpdates.length) * 100).toFixed(1)
};
this.displayBulkResults(results);
return results;
}
displayBulkResults(results) {
console.log('\n📊 Bulk Update Results');
console.log('='.repeat(50));
console.log(`Total Updates: ${results.summary.total}`);
console.log(`✅ Successful: ${results.summary.successful}`);
console.log(`❌ Failed: ${results.summary.failed}`);
console.log(`📈 Success Rate: ${results.summary.successRate}%`);
if (results.successful.length > 0) {
console.log('\n✅ Successfully Updated:');
results.successful.forEach(result => {
console.log(` • ${result.updatedSubscription.name || result.subscriptionId}`);
console.log(` Changes: ${Object.keys(result.appliedChanges).join(', ')}`);
});
}
if (results.failed.length > 0) {
console.log('\n❌ Failed Updates:');
results.failed.forEach(failure => {
console.log(` • ${failure.subscriptionId}`);
console.log(` Error: ${failure.error}`);
});
}
}
getUpdateHistory(subscriptionId) {
const history = Array.from(this.updateHistory.entries())
.filter(([key, record]) => record.subscriptionId === subscriptionId)
.map(([key, record]) => record)
.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp));
return history;
}
displayUpdateHistory(subscriptionId) {
const history = this.getUpdateHistory(subscriptionId);
console.log(`\n📜 Update History for Subscription ${subscriptionId}`);
console.log('='.repeat(60));
if (history.length === 0) {
console.log('No update history found');
return;
}
history.forEach((record, index) => {
console.log(`\n${index + 1}. ${new Date(record.timestamp).toLocaleString()}`);
console.log(` Updated Fields: ${Object.keys(record.updateData).join(', ')}`);
Object.entries(record.updateData).forEach(([field, newValue]) => {
const oldValue = record.previousState[field];
console.log(` ${field}: ${oldValue} → ${newValue}`);
});
});
}
}
// Usage examples
const subscriptionService = new SubscriptionUpdateService("YOUR_API_KEY_HERE");
// Single subscription update with full workflow
const singleUpdate = await subscriptionService.updateSubscription(
"subscription-123e4567-e89b-12d3-a456-426614174000",
{
autoRenew: false,
Ruby__Update_Reason__c: "Customer requested manual renewal"
},
{
validate: true,
enableNotifications: true,
updateReason: "Customer preference change"
}
);
if (singleUpdate.success) {
console.log('✅ Subscription updated successfully');
console.log(`Auto Renew: ${singleUpdate.updatedSubscription.autoRenew}`);
} else {
console.error('❌ Update failed:', singleUpdate.error);
}
// Bulk subscription updates
const bulkUpdates = [
{
subscriptionId: "sub-001",
updateData: { autoRenew: true },
options: { updateReason: "Renewal optimization campaign" }
},
{
subscriptionId: "sub-002",
updateData: { autoRenew: false, Ruby__Manual_Review__c: "true" },
options: { updateReason: "High-value customer manual oversight" }
},
{
subscriptionId: "sub-003",
updateData: { Ruby__Customer_Segment__c: "Enterprise" }
}
];
const bulkResults = await subscriptionService.bulkUpdateSubscriptions(bulkUpdates, {
validate: true,
enableNotifications: true,
batchSize: 3
});
console.log(`Bulk update completed: ${bulkResults.summary.successful}/${bulkResults.summary.total} subscriptions updated`);
// Display update history
subscriptionService.displayUpdateHistory("subscription-123e4567-e89b-12d3-a456-426614174000");Specialized Update Scenarios
Auto-Renewal Management Campaign
Implement a campaign to optimize auto-renewal settings across the subscription portfolio:
class AutoRenewalCampaign {
constructor(subscriptionService) {
this.subscriptionService = subscriptionService;
}
async optimizeAutoRenewalSettings(customerIds, campaignRules) {
console.log(`🎯 Starting auto-renewal optimization campaign for ${customerIds.length} customers...`);
const results = {
analyzed: 0,
updated: 0,
skipped: 0,
errors: 0,
details: []
};
for (const customerId of customerIds) {
try {
// Fetch customer subscriptions
const subscriptions = await this.fetchCustomerSubscriptions(customerId);
results.analyzed += subscriptions.length;
// Analyze and apply campaign rules
for (const subscription of subscriptions) {
const recommendation = this.analyzeSubscriptionForAutoRenewal(subscription, campaignRules);
if (recommendation.shouldUpdate) {
const updateResult = await this.subscriptionService.updateSubscription(
subscription.id,
{ autoRenew: recommendation.newAutoRenewSetting },
{
validate: true,
enableNotifications: true,
updateReason: recommendation.reason
}
);
if (updateResult.success) {
results.updated++;
results.details.push({
subscriptionId: subscription.id,
subscriptionName: subscription.name,
action: 'updated',
oldSetting: subscription.autoRenew,
newSetting: recommendation.newAutoRenewSetting,
reason: recommendation.reason
});
} else {
results.errors++;
results.details.push({
subscriptionId: subscription.id,
action: 'error',
error: updateResult.error
});
}
} else {
results.skipped++;
results.details.push({
subscriptionId: subscription.id,
action: 'skipped',
reason: recommendation.reason
});
}
}
} catch (error) {
console.error(`Error processing customer ${customerId}:`, error);
results.errors++;
}
}
this.displayCampaignResults(results);
return results;
}
async fetchCustomerSubscriptions(customerId) {
// Simplified fetch - in production, use the full subscription service
const encodedIds = encodeURIComponent(JSON.stringify([customerId]));
const response = await fetch(`https://api.nue.io/subscriptions?customerIds=${encodedIds}&status=active`, {
method: 'GET',
headers: this.subscriptionService.headers
});
const result = await response.json();
return result.data || [];
}
analyzeSubscriptionForAutoRenewal(subscription, campaignRules) {
// Apply business rules to determine auto-renewal optimization
// Rule 1: High-value subscriptions should have auto-renewal enabled
if (subscription.totalACV >= campaignRules.highValueThreshold) {
if (!subscription.autoRenew) {
return {
shouldUpdate: true,
newAutoRenewSetting: true,
reason: `High-value subscription ($${subscription.totalACV}) - enabling auto-renewal`
};
}
}
// Rule 2: Low-risk customers with good payment history
if (campaignRules.enableForLowRisk && this.isLowRiskCustomer(subscription)) {
if (!subscription.autoRenew) {
return {
shouldUpdate: true,
newAutoRenewSetting: true,
reason: 'Low-risk customer with good payment history - enabling auto-renewal'
};
}
}
// Rule 3: Subscriptions expiring soon without auto-renewal
const daysToExpiry = this.getDaysToExpiry(subscription.subscriptionEndDate);
if (daysToExpiry <= 60 && !subscription.autoRenew) {
return {
shouldUpdate: true,
newAutoRenewSetting: true,
reason: `Subscription expiring in ${daysToExpiry} days - enabling auto-renewal to prevent churn`
};
}
// Rule 4: Trial subscriptions should not have auto-renewal
if (subscription.name.toLowerCase().includes('trial') && subscription.autoRenew) {
return {
shouldUpdate: true,
newAutoRenewSetting: false,
reason: 'Trial subscription - disabling auto-renewal for manual conversion'
};
}
// No update needed
return {
shouldUpdate: false,
reason: 'Current auto-renewal setting is optimal'
};
}
isLowRiskCustomer(subscription) {
// Simplified risk assessment - in production, integrate with credit/payment systems
// For demo, assume customers with long subscription history are low risk
const startDate = new Date(subscription.subscriptionStartDate);
const monthsActive = Math.floor((new Date() - startDate) / (1000 * 60 * 60 * 24 * 30));
return monthsActive >= 12; // 12+ months = low risk
}
getDaysToExpiry(endDateString) {
const endDate = new Date(endDateString);
const now = new Date();
return Math.ceil((endDate - now) / (1000 * 60 * 60 * 24));
}
displayCampaignResults(results) {
console.log('\n🎯 Auto-Renewal Campaign Results');
console.log('='.repeat(50));
console.log(`📊 Subscriptions Analyzed: ${results.analyzed}`);
console.log(`✅ Updated: ${results.updated}`);
console.log(`⏭️ Skipped: ${results.skipped}`);
console.log(`❌ Errors: ${results.errors}`);
const updateRate = results.analyzed > 0 ? ((results.updated / results.analyzed) * 100).toFixed(1) : 0;
console.log(`📈 Update Rate: ${updateRate}%`);
// Group results by action
const updated = results.details.filter(d => d.action === 'updated');
const skipped = results.details.filter(d => d.action === 'skipped');
const errors = results.details.filter(d => d.action === 'error');
if (updated.length > 0) {
console.log('\n✅ Updated Subscriptions:');
updated.forEach(detail => {
console.log(` • ${detail.subscriptionName}: ${detail.oldSetting} → ${detail.newSetting}`);
console.log(` Reason: ${detail.reason}`);
});
}
if (errors.length > 0) {
console.log('\n❌ Failed Updates:');
errors.forEach(detail => {
console.log(` • ${detail.subscriptionId}: ${detail.error}`);
});
}
console.log('\n💡 Campaign Impact:');
const enabledCount = updated.filter(d => d.newSetting === true).length;
const disabledCount = updated.filter(d => d.newSetting === false).length;
console.log(` Auto-renewal enabled: ${enabledCount} subscriptions`);
console.log(` Auto-renewal disabled: ${disabledCount} subscriptions`);
}
}
// Usage example
const renewalCampaign = new AutoRenewalCampaign(subscriptionService);
const campaignRules = {
highValueThreshold: 50000, // $50k+ subscriptions
enableForLowRisk: true,
disableForTrials: true
};
const customerIds = [
"d2e04653-ae90-49df-a986-134cf64f6d03",
"cc5e1f0f-5e14-48cc-ab98-9e5b191aa46f"
];
const campaignResults = await renewalCampaign.optimizeAutoRenewalSettings(customerIds, campaignRules);
console.log(`Campaign completed: ${campaignResults.updated} subscriptions optimized`);Request Body Schema
Updateable Fields
Field | Type | Description | Example |
|---|---|---|---|
autoRenew | Boolean | Enable/disable automatic renewal | true, false |
{CustomField}__c | String | Custom field value (must match field API name) | "Custom Value" |
Custom Field Naming Convention
Custom fields must follow the pattern: {Namespace}__{FieldName}__c
Examples:
- Ruby__Custom_Field__c
- Organization__Department__c
- Integration__External_ID__c
Response Structure
Success Response (200 OK)
{
"status": "SUCCESS",
"data": [
{
"actualSubscriptionTerm": 12,
"autoRenew": false,
"billCycleDay": "7th of Month",
"billCycleStartMonth": "03",
"billingAccountId": "81dd1eb9-7a2c-4486-be76-b1ac2f88bbb1",
"billingPeriod": "Annual",
"billingTiming": "In Advance",
"bundled": true,
"createdById": "74ef82c9-a9d7-4262-8331-ba7ac33d1f76",
"createdDate": "2025-07-02T23:12:30.582Z",
"customerId": "81dd1eb9-7a2c-4486-be76-b1ac2f88bbb1",
"evergreen": false,
"id": "f594fd3a-3659-4039-ae5c-b2c6863d98a5",
"lastModifiedById": "74ef82c9-a9d7-4262-8331-ba7ac33d1f76",
"lastModifiedDate": "2025-07-02T23:12:30.621Z",
"listPrice": 19.9,
"name": "SUB-00000309",
"nextBillingDate": "2025-07-01",
"orderOnDate": "2025-07-02",
"orderProductId": "03139976-1cc2-4430-8f61-996e641c8745",
"parentId": "3b573778-89c0-491d-a972-bd3073d9add4",
"parentObjectType": "Subscription",
"priceBookEntryId": "01u7z000005YNBAAA4",
"priceBookId": "01s7z000006Dt4rAAC",
"productId": "01t7z00000DXt09AAD",
"quantity": 2,
"renewalTerm": 12,
"rootId": "3b573778-89c0-491d-a972-bd3073d9add4",
"salesPrice": 19.9,
"status": "Active",
"subscriptionCompositeId": "SUB-00000309_1",
"subscriptionEndDate": "2026-06-30",
"subscriptionLevel": 2,
"subscriptionStartDate": "2025-07-01",
"subscriptionTerm": 12,
"subscriptionVersion": 1,
"taxAmount": 0,
"tcv": 0,
"totalACV": 0,
"totalAmount": 0,
"totalPrice": 0,
"totalTCV": 0,
"uomId": "a0s7z00000HYFPTAA5"
}
],
"warnings": []
}Error Handling
Common Update Errors
Error | Description | Resolution |
|---|---|---|
SUBSCRIPTION_NOT_FOUND | Subscription ID doesn't exist | Verify subscription ID |
INVALID_FIELD | Field not updateable or doesn't exist | Check allowed fields and custom field names |
VALIDATION_ERROR | Field value validation failed | Review field constraints and data types |
PERMISSION_ERROR | Insufficient permissions | Verify API key has update permissions |
Robust Update Error Handling
async function safeSubscriptionUpdate(subscriptionId, updateData, options = {}) {
try {
// Validate input data
if (!subscriptionId) {
throw new Error('Subscription ID is required');
}
if (!updateData || Object.keys(updateData).length === 0) {
throw new Error('Update data is required');
}
const response = await fetch(`https://api.nue.io/subscriptions/${subscriptionId}`, {
method: 'PATCH',
headers: myHeaders,
body: JSON.stringify(updateData)
});
if (!response.ok) {
const errorText = await response.text();
// Handle specific error scenarios
if (response.status === 404) {
throw new Error(`Subscription ${subscriptionId} not found`);
} else if (response.status === 400) {
throw new Error(`Invalid update data: ${errorText}`);
} else if (response.status === 403) {
throw new Error('Insufficient permissions to update subscription');
} else {
throw new Error(`Update failed: ${response.status} ${errorText}`);
}
}
const result = await response.json();
if (result.status !== 'SUCCESS') {
throw new Error(`Update failed: ${result.message || 'Unknown error'}`);
}
return {
success: true,
subscription: result.data[0],
updatedFields: Object.keys(updateData)
};
} catch (error) {
console.error(`Subscription update failed for ${subscriptionId}:`, error);
return {
success: false,
subscriptionId,
error: error.message,
updateData
};
}
}Best Practices
Update Strategy
- Validate before updating to prevent API errors
- Track update history for audit and rollback purposes
- Implement business rules to ensure updates align with policies
- Use batch processing for bulk updates with rate limiting
Auto-Renewal Management
- Monitor expiration dates when disabling auto-renewal
- Send notifications for auto-renewal changes
- Schedule follow-up tasks for manual renewals
- Consider customer segments when optimizing auto-renewal
Data Integrity
- Backup current state before making updates
- Validate custom field names and formats
- Implement rollback procedures for failed bulk updates
- Log all changes for compliance and audit
Performance
- Batch updates efficiently to respect rate limits
- Use async processing for large-scale updates
- Implement retry logic for transient failures
- Monitor API usage and optimize call patterns
This comprehensive guide enables you to efficiently update subscription data using the Nue Lifecycle Management API, supporting everything from simple field updates to complex auto-renewal optimization campaigns and bulk subscription management workflows.