Generate Magic Links
This guide provides comprehensive instructions for generating magic links from draft orders using the Nue Lifecycle Management API. Learn how to create shareable PDF quote links with standard or custom branding, manage link security, and implement efficient quote generation workflows.
Prerequisites
Before you begin, ensure you have:
- A valid Nue API key with order management permissions
- Draft order IDs for which you want to generate magic links
- Template IDs for custom branding (optional, configured in your Nue account)
- Understanding of draft order lifecycle and quote generation
- Basic knowledge of REST APIs and JSON
- Familiarity with PDF quote sharing workflows
Authentication
All magic link generation 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 Magic Link Generation
Generate Standard Magic Link
Try it now: Generate Draft Order Magic Link ā
const myHeaders = new Headers();
myHeaders.append("nue-api-key", "YOUR_API_KEY_HERE");
myHeaders.append("Content-Type", "application/json");
// Generate standard magic link for a draft order
const draftOrderId = "123e4567-e89b-12d3-a456-426614174000";
fetch(`https://api.nue.io/orders/magiclink/order/${draftOrderId}`, {
method: 'GET',
headers: myHeaders
})
.then(response => response.json())
.then(result => {
console.log('Magic link generated successfully:', result);
if (result.magicLink) {
console.log('\nā
Standard Magic Link Generated');
console.log(`Order ID: ${draftOrderId}`);
console.log(`Magic Link: ${result.magicLink}`);
// The magic link can be shared with customers
console.log('\nš§ Ready to share with customer for quote review');
console.log('š” Customer can view and download PDF quote without login');
// Example of how to use the link
shareWithCustomer(result.magicLink, null, draftOrderId);
}
})
.catch(error => console.log('Error:', error));
function shareWithCustomer(magicLink, templateId, orderId) {
// Customer communication
const emailTemplate = {
to: '[email protected]',
subject: templateId ? 'Your Branded Quote is Ready' : 'Your Quote is Ready for Review',
body: `
Dear Customer,
Your ${templateId ? 'professionally branded ' : ''}quote is ready for review. Please click the link below to view and download your PDF quote:
${magicLink}
This secure link allows you to:
⢠View your complete quote details
⢠Download a PDF copy for your records
⢠Share with your team for approval
${templateId ? 'Our branded presentation reflects the quality and professionalism you can expect from our partnership.' : ''}
The quote is valid for 30 days. If you have any questions, please contact us.
Best regards,
Sales Team
`
};
console.log('\nš§ Email template prepared:', emailTemplate);
}Generate Branded Magic Link with Custom Template
// Generate branded magic link with custom template
const draftOrderId = "123e4567-e89b-12d3-a456-426614174000";
const templateId = "f47ac10b-58cc-4372-a567-0e02b2c3d479";
fetch(`https://api.nue.io/orders/magiclink/order/${draftOrderId}/template/${templateId}`, {
method: 'GET',
headers: myHeaders
})
.then(response => response.json())
.then(result => {
console.log('Branded magic link generated successfully:', result);
if (result.magicLink) {
console.log('\nā
Branded Magic Link Generated');
console.log(`Order ID: ${draftOrderId}`);
console.log(`Template ID: ${templateId}`);
console.log(`Magic Link: ${result.magicLink}`);
// The branded magic link includes custom styling and branding
console.log('\nšØ Branded quote includes:');
console.log('⢠Custom company logo and colors');
console.log('⢠Branded headers and footers');
console.log('⢠Custom styling and layout');
console.log('⢠Professional branded appearance');
shareWithCustomer(result.magicLink, templateId, draftOrderId);
}
})
.catch(error => console.log('Error:', error));Generate Links for Different Customer Segments
Create magic links using different templates based on customer segments:
async function generateSegmentedMagicLink(draftOrderId, customerSegment) {
const myHeaders = new Headers();
myHeaders.append("nue-api-key", "YOUR_API_KEY_HERE");
myHeaders.append("Content-Type", "application/json");
// Template mapping based on customer segment
const templateMapping = {
'enterprise': 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
'midmarket': '6ba7b810-9dad-11d1-80b4-00c04fd430c8',
'smb': '6ba7b811-9dad-11d1-80b4-00c04fd430c8',
'partner': '6ba7b812-9dad-11d1-80b4-00c04fd430c8',
'trial': '6ba7b813-9dad-11d1-80b4-00c04fd430c8'
};
const templateId = templateMapping[customerSegment];
try {
console.log(`šØ Generating ${customerSegment} quote for order ${draftOrderId}...`);
// Choose endpoint based on whether template is specified
const endpoint = templateId ?
`https://api.nue.io/orders/magiclink/order/${draftOrderId}/template/${templateId}` :
`https://api.nue.io/orders/magiclink/order/${draftOrderId}`;
const response = await fetch(endpoint, {
method: 'GET',
headers: myHeaders
});
if (response.ok) {
const result = await response.json();
return {
success: true,
orderId: draftOrderId,
segment: customerSegment,
templateId: templateId || 'standard',
magicLink: result.magicLink,
brandingFeatures: getBrandingFeatures(customerSegment)
};
} else {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
} catch (error) {
return {
success: false,
orderId: draftOrderId,
segment: customerSegment,
error: error.message
};
}
}
function getBrandingFeatures(segment) {
const features = {
'enterprise': [
'Premium executive-level design',
'Custom enterprise logo placement',
'Executive summary section',
'Advanced security notices',
'White-glove service indicators'
],
'midmarket': [
'Professional business design',
'Company branding integration',
'Scalability messaging',
'ROI highlighting',
'Growth-focused content'
],
'smb': [
'Clean, accessible design',
'Value-focused messaging',
'Easy-to-understand pricing',
'Small business testimonials',
'Quick start guidance'
],
'partner': [
'Co-branded design elements',
'Partner program benefits',
'Channel-specific pricing',
'Partner support information',
'Joint value proposition'
],
'trial': [
'Evaluation-focused design',
'Trial-to-paid messaging',
'Feature comparison charts',
'Implementation timeline',
'Trial extension options'
]
};
return features[segment] || ['Standard design'];
}
// Usage examples for different customer segments
const orderSegmentExamples = [
{ orderId: "order-enterprise-001", segment: "enterprise" },
{ orderId: "order-midmarket-002", segment: "midmarket" },
{ orderId: "order-smb-003", segment: "smb" },
{ orderId: "order-partner-004", segment: "partner" },
{ orderId: "order-trial-005", segment: "trial" }
];
// Generate links for all segments
Promise.all(
orderSegmentExamples.map(example =>
generateSegmentedMagicLink(example.orderId, example.segment)
)
).then(results => {
console.log('\nšØ Segment-Specific Magic Links Generated:');
results.forEach(result => {
if (result.success) {
console.log(`\nā
${result.segment.toUpperCase()} Template:`);
console.log(` Order: ${result.orderId}`);
console.log(` Template: ${result.templateId}`);
console.log(` Link: ${result.magicLink}`);
console.log(` Features:`);
result.brandingFeatures.forEach(feature => {
console.log(` ⢠${feature}`);
});
} else {
console.log(`\nā ${result.segment}: ${result.error}`);
}
});
});Advanced Magic Link Management
Comprehensive Magic Link Service
Implement a service that handles both standard and branded magic link generation:
class MagicLinkService {
constructor(apiKey) {
this.apiKey = apiKey;
this.headers = new Headers();
this.headers.append("nue-api-key", apiKey);
this.headers.append("Content-Type", "application/json");
// Template configuration (in production, load from API or config)
this.templateConfig = this.initializeTemplateConfig();
this.linkTracking = new Map();
}
initializeTemplateConfig() {
return {
'f47ac10b-58cc-4372-a567-0e02b2c3d479': {
name: 'Enterprise Premium',
description: 'High-end branded template for enterprise customers',
features: ['Custom executive design', 'Premium branding', 'Security badges'],
useCase: 'Large enterprise deals > $100k',
approvalRequired: true
},
'6ba7b810-9dad-11d1-80b4-00c04fd430c8': {
name: 'Professional Standard',
description: 'Clean professional template for mid-market',
features: ['Professional layout', 'Company branding', 'ROI focus'],
useCase: 'Mid-market customers $10k-$100k',
approvalRequired: false
},
'6ba7b812-9dad-11d1-80b4-00c04fd430c8': {
name: 'Partner Co-branded',
description: 'Joint branding template for channel partners',
features: ['Co-branded headers', 'Partner benefits', 'Channel pricing'],
useCase: 'Channel partner opportunities',
approvalRequired: false
},
'6ba7b813-9dad-11d1-80b4-00c04fd430c8': {
name: 'Trial Conversion',
description: 'Conversion-focused template for trial users',
features: ['Trial benefits', 'Upgrade messaging', 'Feature highlights'],
useCase: 'Trial to paid conversions',
approvalRequired: false
}
};
}
async generateMagicLink(draftOrderId, options = {}) {
try {
// Step 1: Determine if template should be used
const templateId = options.templateId || this.selectOptimalTemplate(options);
// Step 2: Validate template if specified
if (templateId) {
const templateInfo = this.validateTemplate(templateId);
// Check approval requirements
if (templateInfo.approvalRequired && !options.approved) {
return await this.handleApprovalRequired(draftOrderId, templateId, options);
}
}
// Step 3: Validate order for magic link generation
if (options.validateOrder) {
await this.validateDraftOrder(draftOrderId);
}
// Step 4: Generate the magic link (standard or branded)
const linkResult = await this.requestMagicLink(draftOrderId, templateId);
// Step 5: Track link generation
this.trackLinkGeneration(draftOrderId, templateId, linkResult, options);
// Step 6: Prepare communication
const communication = this.prepareCommunication(
linkResult,
templateId ? this.templateConfig[templateId] : null,
options
);
return {
success: true,
orderId: draftOrderId,
templateId: templateId || 'standard',
templateName: templateId ? this.templateConfig[templateId]?.name : 'Standard',
magicLink: linkResult.magicLink,
branding: templateId ? this.templateConfig[templateId] : null,
communication: communication,
generatedAt: new Date().toISOString()
};
} catch (error) {
console.error(`Magic link generation failed:`, error);
return {
success: false,
orderId: draftOrderId,
templateId: options.templateId,
error: error.message
};
}
}
selectOptimalTemplate(options) {
// Auto-select template based on business rules
const { dealValue, customerSegment, orderType } = options;
if (dealValue >= 100000) return 'f47ac10b-58cc-4372-a567-0e02b2c3d479'; // enterprise-premium
if (customerSegment === 'partner') return '6ba7b812-9dad-11d1-80b4-00c04fd430c8'; // partner-cobranded
if (orderType === 'trial_conversion') return '6ba7b813-9dad-11d1-80b4-00c04fd430c8'; // trial-conversion
if (dealValue >= 10000) return '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; // professional-standard
// Return null for standard template
return null;
}
validateTemplate(templateId) {
const template = this.templateConfig[templateId];
if (!template) {
throw new Error(`Template '${templateId}' not found. Available templates: ${Object.keys(this.templateConfig).join(', ')}`);
}
return template;
}
async handleApprovalRequired(draftOrderId, templateId, options) {
console.log(`ā ļø Template '${templateId}' requires approval for order ${draftOrderId}`);
const approvalRequest = {
orderId: draftOrderId,
templateId: templateId,
requestedBy: options.requestedBy || 'api_user',
reason: options.approvalReason || 'High-value template usage',
submittedAt: new Date().toISOString()
};
return {
success: false,
requiresApproval: true,
approvalRequest: approvalRequest,
message: `Template '${templateId}' requires management approval`
};
}
async validateDraftOrder(draftOrderId) {
console.log(`Validating draft order ${draftOrderId}...`);
// In production, validate order exists and is in Draft status
return true;
}
async requestMagicLink(draftOrderId, templateId) {
// Choose endpoint based on whether template is specified
const endpoint = templateId ?
`https://api.nue.io/orders/magiclink/order/${draftOrderId}/template/${templateId}` :
`https://api.nue.io/orders/magiclink/order/${draftOrderId}`;
const response = await fetch(endpoint, {
method: 'GET',
headers: this.headers
});
if (!response.ok) {
let errorMessage = `Magic link generation failed: ${response.status}`;
if (response.status === 400) {
errorMessage += templateId ?
' - Invalid template ID or order configuration' :
' - Invalid order configuration';
} else if (response.status === 404) {
errorMessage += ' - Order not found or template not found';
}
throw new Error(errorMessage);
}
const result = await response.json();
if (!result.magicLink) {
throw new Error('Magic link not returned in response');
}
return result;
}
trackLinkGeneration(orderId, templateId, linkResult, options) {
const tracking = {
orderId,
templateId: templateId || 'standard',
templateName: templateId ? this.templateConfig[templateId]?.name : 'Standard',
magicLink: linkResult.magicLink,
generatedAt: new Date().toISOString(),
generatedBy: options.requestedBy || 'api',
customerSegment: options.customerSegment,
dealValue: options.dealValue,
purpose: options.purpose || 'quote_generation'
};
this.linkTracking.set(`${orderId}_${templateId || 'standard'}`, tracking);
console.log(`š Magic link tracked: ${orderId} using ${templateId || 'standard'}`);
}
prepareCommunication(linkResult, templateInfo, options) {
const customerName = options.customerName || 'Valued Customer';
const isCustomTemplate = !!templateInfo;
const subject = options.subject ||
(isCustomTemplate ? `Your ${templateInfo.name} Quote is Ready` : 'Your Quote is Ready for Review');
let message;
if (isCustomTemplate) {
const featuresList = templateInfo.features
.map(feature => `ā ${feature}`)
.join('\n ');
message = options.customMessage || `
Dear ${customerName},
Your professionally branded quote has been prepared using our ${templateInfo.name}
template, designed specifically for ${templateInfo.useCase.toLowerCase()}.
View your branded quote: ${linkResult.magicLink}
This premium quote includes:
${featuresList}
Our branded presentation reflects the quality and professionalism you can expect
throughout our partnership. The quote design has been tailored to showcase the
value and benefits specific to your business needs.
The quote is valid for 30 days and includes all the detailed information needed
for your review and approval process.
We look forward to discussing how we can support your objectives.
Best regards,
Your Dedicated Account Team
`;
} else {
message = options.customMessage || `
Dear ${customerName},
Your quote is ready for review. Please click the secure link below to view and download your PDF quote:
${linkResult.magicLink}
This link allows you to:
ā View complete quote details
ā Download PDF for your records
ā Share with your team for approval
The quote is valid for 30 days. If you have any questions or need assistance, please don't hesitate to contact us.
Best regards,
Sales Team
`;
}
return {
to: options.customerEmail,
subject: subject,
message: message,
templateUsed: templateInfo?.name || 'Standard',
branding: templateInfo
};
}
async generateMultipleMagicLinks(orders, globalOptions = {}) {
console.log(`š Generating magic links for ${orders.length} orders...`);
const results = [];
const batchSize = globalOptions.batchSize || 5;
for (let i = 0; i < orders.length; i += batchSize) {
const batch = orders.slice(i, i + batchSize);
const batchPromises = batch.map(order =>
this.generateMagicLink(order.orderId, { ...globalOptions, ...order.options })
);
const batchResults = await Promise.allSettled(batchPromises);
results.push(...batchResults);
// Brief pause between batches
if (i + batchSize < orders.length) {
await new Promise(resolve => setTimeout(resolve, 500));
}
}
// 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š Magic Link Generation Results:`);
console.log(`ā
Successful: ${successful.length}`);
console.log(`ā Failed: ${failed.length}`);
if (successful.length > 0) {
console.log('\nā
Generated Magic Links:');
successful.forEach(result => {
const data = result.value;
console.log(`Order ${data.orderId} (${data.templateName}): ${data.magicLink}`);
});
}
if (failed.length > 0) {
console.log('\nā Failed Generations:');
failed.forEach((result, index) => {
const error = result.status === 'rejected' ? result.reason.message : result.value.error;
console.log(`Order ${orders[index]?.orderId || 'Unknown'}: ${error}`);
});
}
return {
total: orders.length,
successful: successful.length,
failed: failed.length,
links: successful.map(r => r.value),
errors: failed
};
}
getAvailableTemplates() {
return Object.entries(this.templateConfig).map(([id, config]) => ({
id,
name: config.name,
description: config.description,
features: config.features,
useCase: config.useCase,
approvalRequired: config.approvalRequired
}));
}
getLinkAnalytics() {
const history = Array.from(this.linkTracking.values());
const analytics = {
totalGenerated: history.length,
templateUsage: {},
customerSegments: {},
averageDealValue: 0,
topTemplates: []
};
let totalDealValue = 0;
let dealCount = 0;
history.forEach(record => {
// Template usage
analytics.templateUsage[record.templateId] =
(analytics.templateUsage[record.templateId] || 0) + 1;
// Customer segments
if (record.customerSegment) {
analytics.customerSegments[record.customerSegment] =
(analytics.customerSegments[record.customerSegment] || 0) + 1;
}
// Deal values
if (record.dealValue) {
totalDealValue += record.dealValue;
dealCount++;
}
});
analytics.averageDealValue = dealCount > 0 ? totalDealValue / dealCount : 0;
analytics.topTemplates = Object.entries(analytics.templateUsage)
.sort(([,a], [,b]) => b - a)
.map(([templateId, count]) => ({
templateId,
templateName: this.templateConfig[templateId]?.name || templateId,
usageCount: count
}));
return analytics;
}
displayAnalytics() {
const analytics = this.getLinkAnalytics();
console.log('\nš Magic Link Analytics');
console.log('='.repeat(40));
console.log(`Total Generated: ${analytics.totalGenerated}`);
console.log(`Average Deal Value: $${analytics.averageDealValue.toLocaleString()}`);
console.log('\nšØ Template Usage:');
analytics.topTemplates.forEach(template => {
console.log(` ${template.templateName}: ${template.usageCount} uses`);
});
if (Object.keys(analytics.customerSegments).length > 0) {
console.log('\nš„ Customer Segments:');
Object.entries(analytics.customerSegments).forEach(([segment, count]) => {
console.log(` ${segment}: ${count} quotes`);
});
}
}
}
// Usage examples
const magicLinkService = new MagicLinkService("YOUR_API_KEY_HERE");
// Display available templates
console.log('\nšØ Available Templates:');
magicLinkService.getAvailableTemplates().forEach(template => {
console.log(`\n${template.name} (${template.id})`);
console.log(` ${template.description}`);
console.log(` Use Case: ${template.useCase}`);
console.log(` Features: ${template.features.join(', ')}`);
console.log(` Approval Required: ${template.approvalRequired ? 'Yes' : 'No'}`);
});
// Generate standard magic link
const standardLink = await magicLinkService.generateMagicLink(
"123e4567-e89b-12d3-a456-426614174000",
{
customerName: "Standard Customer",
customerEmail: "[email protected]",
validateOrder: true
}
);
// Generate branded magic link for enterprise customer
const enterpriseLink = await magicLinkService.generateMagicLink(
"456e7890-e89b-12d3-a456-426614174001",
{
templateId: "f47ac10b-58cc-4372-a567-0e02b2c3d479", // enterprise-premium
customerName: "Enterprise Corp",
customerEmail: "[email protected]",
customerSegment: "enterprise",
dealValue: 250000,
requestedBy: "account_manager"
}
);
// Generate links with auto-template selection
const autoTemplateLink = await magicLinkService.generateMagicLink(
"789e1234-e89b-12d3-a456-426614174002",
{
customerName: "Mid-Market Inc",
customerEmail: "[email protected]",
customerSegment: "midmarket",
dealValue: 75000, // Will auto-select professional-standard template
validateOrder: true
}
);
// Bulk generation with mixed templates
const bulkOrders = [
{
orderId: "bulk-order-001",
options: {
templateId: "f47ac10b-58cc-4372-a567-0e02b2c3d479", // enterprise-premium
customerName: "Enterprise Customer",
customerEmail: "[email protected]"
}
},
{
orderId: "bulk-order-002",
options: {
customerName: "Standard Customer",
customerEmail: "[email protected]"
}
},
{
orderId: "bulk-order-003",
options: {
templateId: "6ba7b812-9dad-11d1-80b4-00c04fd430c8", // partner-cobranded
customerName: "Partner Company",
customerEmail: "[email protected]"
}
}
];
const bulkResults = await magicLinkService.generateMultipleMagicLinks(bulkOrders);
console.log(`Bulk generation completed: ${bulkResults.successful}/${bulkResults.total} links created`);
// Display analytics
magicLinkService.displayAnalytics();Response Structure
Success Response (200 OK)
Standard Magic Link:
{
"magicLink": "https://quotes.nue.io/order/123e4567-e89b-12d3-a456-426614174000"
}Branded Magic Link with Template:
{
"magicLink": "https://quotes.nue.io/order/123e4567-e89b-12d3-a456-426614174000/template/custom-branded-template"
}Error Handling
Common Magic Link Errors
Error Code | Description | Resolution |
|---|---|---|
ORDER_NOT_FOUND | Draft order doesn't exist | Verify order ID is correct |
INVALID_ORDER_STATUS | Order not in Draft status | Ensure order is in Draft state |
INVALID_TEMPLATE_ID | Template ID is invalid or not accessible | Verify template ID and permissions |
TEMPLATE_NOT_FOUND | Specified template does not exist | Check available templates |
TEMPLATE_APPROVAL_REQUIRED | Template requires approval for use | Submit for approval or use different template |
Robust Error Handling
async function safeMagicLinkGeneration(draftOrderId, templateId = null) {
try {
const endpoint = templateId ?
`https://api.nue.io/orders/magiclink/order/${draftOrderId}/template/${templateId}` :
`https://api.nue.io/orders/magiclink/order/${draftOrderId}`;
const response = await fetch(endpoint, {
method: 'GET',
headers: myHeaders
});
if (!response.ok) {
const errorText = await response.text();
if (response.status === 400 && templateId) {
throw new Error(`Template '${templateId}' is invalid or not accessible`);
} else if (response.status === 404) {
throw new Error(`Order ${draftOrderId}${templateId ? ` or template ${templateId}` : ''} not found`);
} else if (response.status === 403 && templateId) {
throw new Error(`Template '${templateId}' requires approval or higher permissions`);
} else {
throw new Error(`Generation failed: ${response.status} ${errorText}`);
}
}
const result = await response.json();
if (!result.magicLink) {
throw new Error('Magic link not returned in response');
}
return {
success: true,
magicLink: result.magicLink,
orderId: draftOrderId,
templateId: templateId || 'standard'
};
} catch (error) {
console.error(`Magic link generation failed:`, error);
return {
success: false,
orderId: draftOrderId,
templateId: templateId,
error: error.message
};
}
}Best Practices
Template Selection
- Use appropriate templates based on customer segment and deal value
- Implement approval workflows for premium templates
- Track template performance and customer engagement
- Regular template updates to maintain brand consistency
Link Management
- Track link generation for analytics and follow-up
- Set appropriate expiration times for quotes
- Monitor link usage to gauge customer engagement
- Provide clear instructions to customers about link usage
Customer Experience
- Select templates that match customer expectations
- Personalize communication about template features and branding
- Highlight value proposition in branded presentations
- Provide template options for important deals
Performance and Security
- Generate links efficiently using batch processing
- Validate template permissions before generation
- Monitor template usage for compliance
- Implement fallback to standard for error scenarios
This comprehensive guide enables you to efficiently generate both standard and branded magic links using the Nue Lifecycle Management API, supporting everything from simple quote sharing to sophisticated branded customer experiences with intelligent template selection.