Activate Draft Orders
This guide provides comprehensive instructions for activating draft orders using the Nue Lifecycle Management API. Learn how to convert draft orders into active orders, configure invoice generation, and implement efficient order activation workflows.
Prerequisites
Before you begin, ensure you have:
- A valid Nue API key with order activation permissions
- Draft order IDs that are ready for activation
- Understanding of invoice generation and activation options
- Basic knowledge of REST APIs and JSON
- Familiarity with order lifecycle management
Authentication
All order activation 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 Order Activation
Activate Draft Order with Invoice Generation
Try it now: Activate Draft Order ā
const myHeaders = new Headers();
myHeaders.append("nue-api-key", "YOUR_API_KEY_HERE");
myHeaders.append("Content-Type", "application/json");
// Activate a draft order with invoice generation
const draftOrderId = "draft-order-123e4567-e89b-12d3-a456-426614174000";
const activationData = {
options: {
generateInvoice: true, // Generate invoice during activation
activateInvoice: false // Keep invoice as draft for manual review
}
};
fetch(`https://api.nue.io/orders/${draftOrderId}`, {
method: 'POST',
headers: myHeaders,
body: JSON.stringify(activationData)
})
.then(response => response.json())
.then(result => {
console.log('Order activated successfully:', result);
if (result.status === 'SUCCESS') {
const order = result.data.order;
console.log(`Order ID: ${order.id}`);
console.log(`Order Number: ${order.orderNumber}`);
console.log(`Status: ${order.status}`); // "Activated"
console.log(`Activation Date: ${order.activatedDate}`);
// Display created assets
if (result.data.assets && result.data.assets.length > 0) {
console.log(`\nš¦ Assets Created: ${result.data.assets.length}`);
result.data.assets.forEach(asset => {
console.log(`- ${asset.productName}: ${asset.quantity} units`);
console.log(` Asset ID: ${asset.id}`);
console.log(` Status: ${asset.status}`);
console.log(` Period: ${asset.startDate} to ${asset.endDate}`);
});
}
// Display invoice information
if (result.data.invoices && result.data.invoices.length > 0) {
const invoice = result.data.invoices[0].invoice;
console.log(`\nš° Invoice Generated:`);
console.log(`Invoice ID: ${invoice.id}`);
console.log(`Amount: $${invoice.amount}`);
console.log(`Status: ${invoice.status}`); // "Draft" when activateInvoice is false
console.log(`Due Date: ${invoice.dueDate}`);
}
}
})
.catch(error => console.log('Error:', error));Activate Order with Immediate Invoice Activation
Activate both the order and generated invoice in one operation:
const immediateActivation = {
options: {
generateInvoice: true,
activateInvoice: true // Immediately activate the generated invoice
},
// Optional: Add purchase order details
poNumber: "PO-2025-67890",
poDate: "2025-01-15"
};
fetch(`https://api.nue.io/orders/${draftOrderId}`, {
method: 'POST',
headers: myHeaders,
body: JSON.stringify(immediateActivation)
})
.then(response => response.json())
.then(result => {
if (result.status === 'SUCCESS') {
const order = result.data.order;
const invoice = result.data.invoices[0].invoice;
console.log('ā
Order and Invoice Activated Successfully');
console.log(`Order Status: ${order.status}`);
console.log(`Invoice Status: ${invoice.status}`); // "Active" when activateInvoice is true
console.log(`Invoice Balance: $${invoice.balance}`);
console.log(`Payment Due: ${invoice.dueDate}`);
// Ready for customer billing
console.log('\nšÆ Order fully activated and ready for billing');
}
})
.catch(error => console.log('Activation failed:', error));Advanced Activation Patterns
Synchronous Payment Processing
When activating orders through self-service flows (e.g., a checkout page), you can confirm payment synchronously before committing the order to the database. Set processPayment: true to enable this mode.
How it works:
- The order is computed entirely in memory ā no database writes yet
- An invoice is generated and payment is charged via Stripe
- If payment succeeds, the order, subscriptions, and invoice are all committed atomically
- If payment fails, behavior depends on cancelOnPaymentFail
cancelOnPaymentFail: true ā Full rollback. Nothing is written to the database. The order stays in Draft status and can be retried with a corrected payment method. Returns HTTP 400.
cancelOnPaymentFail: false ā Commit anyway. The order is activated and subscriptions are created even though payment failed. Returns HTTP 207 with a payment failure warning. You can retry collection later.
Important notes:
- generateInvoice and activateInvoice must both be true when processPayment: true
- For change orders that produce a negative invoice (e.g., cancellations), payment is automatically skipped regardless of these flags ā the credit memo is committed normally
- paymentMethodObject is optional when a default payment method is already on file for the Stripe customer
// Synchronous payment ā full rollback on failure
const syncPaymentActivation = {
options: {
processPayment: true, // Enable synchronous payment mode
cancelOnPaymentFail: true, // Roll back everything if payment fails
generateInvoice: true, // Required with processPayment
activateInvoice: true // Required with processPayment
},
transactionHub: {
externalSystem: "Stripe",
externalId: "cus_RsS1MZKCy2PmJ7", // Stripe customer ID
transactionType: "Customer"
},
paymentMethodObject: {
externalPaymentMethodId: "pm_1RCqTHRqbULxAkCMLnnv6B1R",
name: "Visa ending 4242",
paymentMethodType: "Credit Card",
paymentSystem: "Stripe",
autoChargeEnabled: true
}
};
const response = await fetch(`https://api.nue.io/orders/${draftOrderId}`, {
method: 'POST',
headers: myHeaders,
body: JSON.stringify(syncPaymentActivation)
});
// HTTP 201 ā payment confirmed, everything committed
if (response.status === 201) {
const result = await response.json();
const invoice = result.data.invoices[0].invoice;
console.log('ā
Order activated and payment confirmed');
console.log(`Invoice: ${invoice.id} | Status: ${invoice.paymentStatus}`); // Paid
}
// HTTP 207 ā activated but payment failed (cancelOnPaymentFail: false only)
if (response.status === 207) {
const result = await response.json();
console.log('ā ļø Order activated but payment failed:', result.errorCode);
// result.data contains the activated order ā retry payment separately
}
// HTTP 400 ā payment failed, full rollback (cancelOnPaymentFail: true)
if (response.status === 400) {
const result = await response.json();
console.log('ā Payment failed, order rolled back:', result.message);
// Order is still Draft ā safe to retry with updated payment method
}Setting Custom Fields and revenueContractId During Activation
When activating a draft order, you can set custom fields or revenueContractId on specific order products in the same request. This is useful for scenarios where field values need to be populated before the activation event triggers downstream syncs (e.g., RightRev revenue contract grouping via SQS).
The order product updates are applied before activation commits, so synced systems receive the updated field values immediately.
const activationWithCustomFields = {
options: {
generateInvoice: true,
activateInvoice: true
},
// Set custom fields and revenueContractId on specific order products
orderProducts: [
{
id: "2b0c1858-0706-403e-a6fb-412fd5d161a3", // Order product ID (from draft order)
revenueContractId: "ORD-001234", // Groups revenue contracts in RightRev
TechnicalContactId__c: "003XX000004C0000" // Salesforce custom field
},
{
id: "3c1d2969-1817-514f-b7gc-523ge6e272b4",
revenueContractId: "ORD-001234",
Custom_Field__c: "Value1"
}
]
};
fetch(`https://api.nue.io/orders/${draftOrderId}`, {
method: 'POST',
headers: myHeaders,
body: JSON.stringify(activationWithCustomFields)
})
.then(response => response.json())
.then(result => {
if (result.status === 'SUCCESS') {
console.log('ā
Order activated with custom fields set on order products');
}
})
.catch(error => console.log('Error:', error));Supported fields in the orderProducts activation array:
Field Category | Example | Supported |
|---|---|---|
Standard Nue field | revenueContractId | Yes |
Salesforce custom fields | Custom_Field__c, TechnicalContactId__c | Yes |
System fields | id, createdDate, lastModifiedDate | No ā read-only |
Billing fields | quantity, effectivePrice, listPrice | No ā use existing APIs |
Important: Custom fields must already exist on the Order Product object in Salesforce, be added to the Fields Exposed to Nue field set, and have been synced to Nue before use. See Manage Custom Fields for setup instructions.
Order Activation with Payment Method Integration
For orders using Nue Collections (Payment Links), you can specify or override payment methods during activation:
const nueCollectionsActivation = {
options: {
generateInvoice: true,
activateInvoice: true
},
// Transaction hub (required for payment integration)
transactionHub: {
externalSystem: "Stripe",
externalId: "cus_RsS1MZKCy2PmJ7", // Stripe customer ID
transactionType: "Customer"
},
// Payment method for Nue Collections (overrides draft order payment method)
paymentMethodObject: {
externalPaymentMethodId: "pm_1RCqTHRqbULxAkCMLnnv6B1R",
name: "Updated Payment Method",
paymentMethodType: "Credit Card",
paymentSystem: "Stripe",
autoChargeEnabled: true
}
};
fetch(`https://api.nue.io/orders/${draftOrderId}`, {
method: 'POST',
headers: myHeaders,
body: JSON.stringify(nueCollectionsActivation)
})
.then(response => response.json())
.then(result => {
if (result.status === 'SUCCESS') {
console.log('ā
Order activated with Nue Collections payment method');
// The created subscriptions will have defaultPaymentMethodId set
const subscriptions = result.data.subscriptions || [];
subscriptions.forEach(sub => {
console.log(`Subscription ${sub.name}: Payment Method ${sub.defaultPaymentMethodId}`);
});
}
})
.catch(error => console.log('Nue Collections activation failed:', error));Order Activation with External System Integration
For Stripe Invoicing integration (transaction hub only):
const externalSystemActivation = {
options: {
generateInvoice: true,
activateInvoice: true
},
// Purchase order information
poNumber: "PO-2025-ENTERPRISE-001",
poDate: "2025-01-10",
// External system tracking (required for Stripe Invoicing)
transactionHub: {
externalSystem: "Stripe", // External payment system
externalId: "cus_RsS1MZKCy2PmJ7", // Stripe customer ID
transactionType: "Customer" // Transaction type
}
};
fetch(`https://api.nue.io/orders/${draftOrderId}`, {
method: 'POST',
headers: myHeaders,
body: JSON.stringify(externalSystemActivation)
})
.then(response => response.json())
.then(result => {
if (result.status === 'SUCCESS') {
console.log('ā
Order activated with external system integration');
console.log(`External System: ${result.data.order.transactionHub?.externalSystem}`);
console.log(`External Transaction ID: ${result.data.order.transactionHub?.externalId}`);
// Update external system with Nue order details
updateExternalSystem(result.data.order);
}
})
.catch(error => console.log('External integration activation failed:', error));
function updateExternalSystem(order) {
// Integrate with your external payment/ERP system
console.log(`Updating external system with order ${order.orderNumber}`);
// Example: Update Stripe subscription with Nue order details
const externalUpdate = {
nueOrderId: order.id,
nueOrderNumber: order.orderNumber,
activationDate: order.activatedDate,
totalAmount: order.grandTotal
};
console.log('External system update payload:', externalUpdate);
}Bulk Order Activation Service
Implement a service to activate multiple draft orders efficiently:
class OrderActivationService {
constructor(apiKey) {
this.apiKey = apiKey;
this.headers = new Headers();
this.headers.append("nue-api-key", apiKey);
this.headers.append("Content-Type", "application/json");
}
async activateOrder(draftOrderId, activationOptions = {}) {
try {
// Default activation configuration
const defaultOptions = {
generateInvoice: true,
activateInvoice: false, // Conservative default
validateBeforeActivation: true
};
const options = { ...defaultOptions, ...activationOptions };
// Step 1: Validate order before activation (optional)
if (options.validateBeforeActivation) {
await this.validateOrderForActivation(draftOrderId);
}
// Step 2: Prepare activation payload
const activationPayload = this.prepareActivationPayload(options);
// Step 3: Activate the order
const result = await this.submitActivation(draftOrderId, activationPayload);
// Step 4: Process activation result
const processedResult = this.processActivationResult(result);
// Step 5: Handle post-activation tasks
await this.handlePostActivation(processedResult);
return {
success: true,
order: processedResult.order,
assets: processedResult.assets,
invoices: processedResult.invoices,
summary: this.generateActivationSummary(processedResult)
};
} catch (error) {
console.error(`Order activation failed for ${draftOrderId}:`, error);
return {
success: false,
error: error.message,
draftOrderId
};
}
}
async validateOrderForActivation(draftOrderId) {
// In a real implementation, you might fetch the draft order
// and validate business rules before activation
console.log(`Validating order ${draftOrderId} for activation...`);
// Example validations:
// - Check customer payment status
// - Verify product availability
// - Confirm pricing is current
// - Validate subscription terms
return true;
}
prepareActivationPayload(options) {
const payload = {
options: {
generateInvoice: options.generateInvoice,
activateInvoice: options.activateInvoice
}
};
// Add PO information if provided
if (options.poNumber) {
payload.poNumber = options.poNumber;
}
if (options.poDate) {
payload.poDate = options.poDate;
}
// Add external system integration if provided
if (options.transactionHub) {
payload.transactionHub = options.transactionHub;
}
return payload;
}
async submitActivation(draftOrderId, payload) {
const response = await fetch(`https://api.nue.io/orders/${draftOrderId}`, {
method: 'POST',
headers: this.headers,
body: JSON.stringify(payload)
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Activation failed: ${response.status} ${errorText}`);
}
const result = await response.json();
if (result.status !== 'SUCCESS') {
throw new Error(`Activation failed: ${result.message || 'Unknown error'}`);
}
return result;
}
processActivationResult(apiResult) {
return {
order: apiResult.data.order,
assets: apiResult.data.assets || [],
invoices: apiResult.data.invoices || [],
entitlements: apiResult.data.entitlements || []
};
}
async handlePostActivation(result) {
const order = result.order;
// Example post-activation tasks:
// 1. Send activation notifications
await this.sendActivationNotifications(order);
// 2. Update customer records
await this.updateCustomerRecords(order);
// 3. Provision services
await this.provisionServices(result.assets);
// 4. Setup monitoring/tracking
await this.setupOrderTracking(order);
}
async sendActivationNotifications(order) {
console.log(`š§ Sending activation notifications for order ${order.orderNumber}...`);
// Notify customer
const customerNotification = {
to: order.customerEmail,
subject: `Order ${order.orderNumber} Activated`,
template: 'order_activation',
data: {
orderNumber: order.orderNumber,
activationDate: order.activatedDate,
nextBillingDate: order.nextBillingDate
}
};
// Notify internal teams
const internalNotification = {
to: '[email protected]',
subject: `Order Activated: ${order.orderNumber}`,
template: 'internal_order_activation',
data: {
orderNumber: order.orderNumber,
customerName: order.customerName,
totalValue: order.grandTotal
}
};
console.log('ā
Activation notifications queued');
}
async updateCustomerRecords(order) {
console.log(`š Updating customer records for ${order.customerName}...`);
// Update customer lifecycle stage
// Update account values
// Record activation event
console.log('ā
Customer records updated');
}
async provisionServices(assets) {
console.log(`š Provisioning services for ${assets.length} assets...`);
for (const asset of assets) {
// Provision each service/product
console.log(`- Provisioning ${asset.productName} (${asset.quantity} units)`);
// Integration points:
// - Create user accounts
// - Setup service configurations
// - Deploy infrastructure
// - Configure access controls
}
console.log('ā
Service provisioning completed');
}
async setupOrderTracking(order) {
console.log(`š Setting up tracking for order ${order.orderNumber}...`);
// Setup monitoring and analytics
const trackingData = {
orderId: order.id,
orderNumber: order.orderNumber,
activationDate: order.activatedDate,
customerSegment: order.customerSegment,
orderValue: order.grandTotal,
subscriptionEndDate: order.subscriptionEndDate
};
console.log('ā
Order tracking configured');
}
generateActivationSummary(result) {
const order = result.order;
const assets = result.assets;
const invoices = result.invoices;
return {
orderId: order.id,
orderNumber: order.orderNumber,
customerName: order.customerName,
activationDate: order.activatedDate,
status: order.status,
totalAssets: assets.length,
activeAssets: assets.filter(a => a.status === 'Active').length,
totalInvoices: invoices.length,
postedInvoices: invoices.filter(i => i.status === 'Posted').length,
totalValue: order.grandTotal,
nextBillingDate: order.nextBillingDate
};
}
async activateMultipleOrders(draftOrderIds, globalOptions = {}) {
const results = [];
const batchSize = 5; // Process in batches to avoid rate limits
console.log(`š Activating ${draftOrderIds.length} orders in batches of ${batchSize}...`);
for (let i = 0; i < draftOrderIds.length; i += batchSize) {
const batch = draftOrderIds.slice(i, i + batchSize);
console.log(`Processing batch ${Math.floor(i/batchSize) + 1}...`);
const batchPromises = batch.map(orderId =>
this.activateOrder(orderId, globalOptions)
);
const batchResults = await Promise.allSettled(batchPromises);
results.push(...batchResults);
// Brief pause between batches
if (i + batchSize < draftOrderIds.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
// Analyze results
const successful = results.filter(r => r.status === 'fulfilled' && r.value.success);
const failed = results.filter(r => r.status === 'rejected' || !r.value.success);
console.log(`\nš Bulk Activation Results:`);
console.log(`ā
Successful: ${successful.length}`);
console.log(`ā Failed: ${failed.length}`);
if (failed.length > 0) {
console.log('\nā Failed Activations:');
failed.forEach(result => {
const error = result.status === 'rejected' ? result.reason : result.value.error;
console.log(`- Order: ${result.value?.draftOrderId || 'Unknown'} - ${error}`);
});
}
return {
total: draftOrderIds.length,
successful: successful.length,
failed: failed.length,
results: results
};
}
}
// Usage examples
const activationService = new OrderActivationService("YOUR_API_KEY_HERE");
// Single order activation
const singleActivation = await activationService.activateOrder(
"draft-order-123",
{
generateInvoice: true,
activateInvoice: true,
poNumber: "PO-2025-001",
transactionHub: {
externalSystem: "Salesforce",
externalId: "006XX000004C0000",
transactionType: "Opportunity"
}
}
);
if (singleActivation.success) {
console.log(`ā
Order ${singleActivation.summary.orderNumber} activated successfully`);
console.log(`Assets Created: ${singleActivation.summary.totalAssets}`);
console.log(`Total Value: $${singleActivation.summary.totalValue}`);
} else {
console.error(`ā Activation failed: ${singleActivation.error}`);
}
// Bulk order activation
const bulkOrderIds = [
"draft-order-123",
"draft-order-456",
"draft-order-789"
];
const bulkResult = await activationService.activateMultipleOrders(
bulkOrderIds,
{
generateInvoice: true,
activateInvoice: false, // Keep invoices as draft for review
validateBeforeActivation: true
}
);
console.log(`Bulk activation completed: ${bulkResult.successful}/${bulkResult.total} orders activated`);Order Activation Workflows
Approval-Based Activation
Implement approval workflows for high-value orders:
class ApprovalBasedActivationService extends OrderActivationService {
async activateOrderWithApproval(draftOrderId, options = {}) {
try {
// Step 1: Check if order requires approval
const requiresApproval = await this.checkApprovalRequirement(draftOrderId);
if (requiresApproval) {
// Step 2: Submit for approval
const approvalResult = await this.submitForApproval(draftOrderId);
if (!approvalResult.approved) {
return {
success: false,
requiresApproval: true,
approvalId: approvalResult.approvalId,
message: 'Order submitted for approval'
};
}
}
// Step 3: Proceed with activation
return await this.activateOrder(draftOrderId, options);
} catch (error) {
return {
success: false,
error: error.message,
draftOrderId
};
}
}
async checkApprovalRequirement(draftOrderId) {
// Business logic to determine if approval is needed
// Examples:
// - Order value > $10,000
// - Custom pricing applied
// - Non-standard terms
// - New customer
console.log(`Checking approval requirements for order ${draftOrderId}...`);
// Mock approval check
const orderValue = 15000; // Would fetch actual order value
return orderValue > 10000;
}
async submitForApproval(draftOrderId) {
console.log(`Submitting order ${draftOrderId} for approval...`);
// Integration with approval system
const approvalRequest = {
orderId: draftOrderId,
approvalType: 'order_activation',
submittedBy: 'api_user',
submittedDate: new Date().toISOString(),
urgency: 'normal'
};
// Mock approval submission
return {
approved: false, // Would be determined by approval system
approvalId: `approval-${Date.now()}`,
estimatedApprovalTime: '2-4 hours'
};
}
}Request Body Schema
Required Fields
Field | Type | Description | Example |
|---|---|---|---|
options | Object | Activation configuration options | See options schema below |
options.generateInvoice | Boolean | Whether to generate invoice during activation | true |
options.activateInvoice | Boolean | Whether to activate the generated invoice | false |
Optional Fields
Field | Type | Description | Example |
|---|---|---|---|
options.processPayment | Boolean | Enable synchronous payment confirmation before committing order data | true |
options.cancelOnPaymentFail | Boolean | When processPayment: true ā if true, roll back everything on payment failure (HTTP 400); if false, commit the order anyway and return HTTP 207 with a warning. Requires processPayment: true. | true |
poNumber | String | Purchase order number | "PO-2025-67890" |
poDate | String | Purchase order date (YYYY-MM-DD) | "2025-01-15" |
transactionHub | Object | External system integration | See transaction hub schema |
paymentMethodObject | Object | Payment method for Nue Collections. Optional when processPayment: true if Stripe customer has a default PM on file. | See payment method schema |
orderProducts | Array | Order products to update with custom fields or revenueContractId before activation. Each entry requires an id (order product UUID from the draft order) plus the fields to set. | See supported fields table above |
Payment Method Override Behavior:
- Payment method provided during activation will override the payment method from draft order creation
- Product-level and add-on level payment methods from draft creation are still respected
- If no payment method is provided during activation, the draft order payment methods are used
Transaction Hub Schema
Field | Type | Description | Example |
|---|---|---|---|
externalSystem | String | External system identifier | "Stripe", "Salesforce" |
externalId | String | External transaction/record ID | "cus_RsS1MZKCy2PmJ7" |
transactionType | String | Type of external transaction | "Customer", "Opportunity" |
Payment Method Object Schema
Field | Type | Required | Description | Valid Values |
|---|---|---|---|---|
externalPaymentMethodId | String | Yes* | External payment method ID (e.g., Stripe PM ID) | Any string |
name | String | Yes* | Display name for the payment method | Any string |
paymentMethodType | String | Yes* | Type of payment method | "Electronic", "NonElectronic", "ACH", "Bank Transfer", "Cash", "Check", "Credit Card", "Debit Card", "Paypal", "Wire Transfer", "Other" |
paymentSystem | String | Yes* | Payment system identifier (e.g., "Stripe") | Any string |
autoChargeEnabled | Boolean | Yes* | Whether automatic charging is enabled | true or false |
id | String | Yes** | Existing Nue payment method ID | UUID format |
*Required when creating a new payment method from external system **Required when referencing an existing Nue payment method
Response Structure
HTTP Status Codes
HTTP Status | When | Description |
|---|---|---|
201 Created | Standard activation or processPayment: true with successful payment | Order activated, invoice generated |
207 Multi-Status | processPayment: true, payment failed, cancelOnPaymentFail: false | Order activated despite payment failure. Check errorCode for payment details |
400 Bad Request | Validation error, or processPayment: true + payment failed + cancelOnPaymentFail: true | Nothing committed. Order stays Draft and can be retried |
Success Response (201 Created)
{
"status": "SUCCESS",
"data": {
"order": {
"id": "order-uuid",
"orderNumber": "O-00005049",
"status": "Activated",
"activatedDate": "2026-07-25T01:55:27.273+00:00",
"customerId": "001HE00000KY3w7YAD",
"listTotal": 240,
"subtotal": 216,
"tax": 0,
"totalAmountWithoutTax": 216,
"totalAmount": 216
},
"assets": [
{
"id": "asset-uuid",
"productName": "Enterprise License",
"status": "Active",
"quantity": 100,
"startDate": "2025-01-15",
"endDate": "2026-01-14"
}
],
"invoices": [
{
"invoice": {
"id": "invoice-uuid",
"amount": 9720.00,
"balance": 0,
"status": "Active",
"paymentStatus": "Paid",
"dueDate": "2025-02-14"
}
}
],
"entitlements": []
}
}Payment Failure Response (207 Multi-Status)
Returned when processPayment: true, cancelOnPaymentFail: false, and payment fails. The order and subscriptions are committed; payment must be retried separately.
{
"status": "PARTIAL_SUCCESS",
"errorType": "PAYMENT_PROCESSING_FAILED",
"errorCode": "PAYMENT_FAILED",
"message": "Payment processing failed: ...",
"data": {
"order": { "status": "Activated" },
"subscriptions": [...],
"invoices": [{ "invoice": { "paymentStatus": null } }]
}
}Error Handling
Common Activation Errors
Error | Description | Resolution |
|---|---|---|
INVALID_DRAFT_ORDER | Order not found or not in Draft status | Verify order ID and status |
INVOICE_GENERATION_FAILED | Invoice creation failed | Check billing configuration |
ASSET_PROVISIONING_FAILED | Asset creation failed | Review product configuration |
ACTIVATION_VALIDATION_FAILED | Pre-activation validation failed | Address validation issues |
SYNC_PAYMENT_REQUIRES_INVOICE_GENERATION | processPayment: true but generateInvoice or activateInvoice is false | Set both generateInvoice: true and activateInvoice: true |
CANCEL_ON_PAYMENT_FAIL_REQUIRES_SYNC_PAYMENT | cancelOnPaymentFail: true without processPayment: true | Only use cancelOnPaymentFail when processPayment: true |
PAYMENT_FAILED | Stripe payment was declined or failed | Check payment method validity and retry |
INVALID_ORDER_PRODUCT_ID | An order product ID in the orderProducts array does not belong to this order | Verify the order product IDs from the draft order |
INVALID_ORDER_PRODUCT_FIELD | A field in the orderProducts array cannot be updated via the activation payload (e.g., billing fields like quantity) | Use billing-specific APIs for those fields instead |
Robust Error Handling
async function safeOrderActivation(draftOrderId, options) {
try {
const result = await activationService.activateOrder(draftOrderId, options);
if (result.success) {
console.log('ā
Order activated successfully');
return result;
} else {
console.error('ā Activation failed:', result.error);
// Handle specific error scenarios
if (result.error.includes('INVALID_DRAFT_ORDER')) {
console.log('š” Check that order exists and is in Draft status');
} else if (result.error.includes('INVOICE_GENERATION_FAILED')) {
console.log('š” Review customer billing configuration');
}
return result;
}
} catch (error) {
console.error('Unexpected activation error:', error);
return {
success: false,
error: error.message,
draftOrderId
};
}
}Best Practices
Activation Strategy
- Validate before activation to prevent failures
- Use conservative invoice settings (generate but don't activate) for manual review
- Implement approval workflows for high-value orders
- Track activation events for audit and analytics
Post-Activation Tasks
- Send customer notifications about service activation
- Provision services immediately after activation
- Update external systems with activation details
- Monitor asset status and usage
Error Recovery
- Implement retry logic for transient failures
- Provide clear error messages to users
- Log activation attempts for troubleshooting
- Have rollback procedures for failed activations
This comprehensive guide enables you to efficiently activate draft orders using the Nue Lifecycle Management API, supporting everything from simple activations to complex approval-based workflows with external system integrations.