Back to Home

Integration Guide

Complete guide for integrating JanusAI License Server into your applications

Quick Start

1. Create Your Product

Log into the admin panel and navigate to Products. Create a new product with:

  • Product Code: JANUS-CHAT (unique identifier)
  • Product Name: JanusAI Chat Application
  • Version: 1.0.0
  • Features: ["basic-chat", "voice-input", "file-sharing"]

2. Generate a License

Navigate to Licenses and create a new license:

  • Select your product
  • Set expiration date
  • Define machine activation limit
  • Configure allowed features

3. Integrate the API

// Basic validation request
const response = await fetch('https://your-domain.com/api/v1/validate', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    licenseKey: 'your-license-key',
    productCode: 'JANUS-CHAT',
    machineId: getMachineId(),
    requireActivation: true
  })
});

const result = await response.json();
if (result.status === 'valid') {
  // License is valid, enable features
  enableFeatures(result.features);
}
Desktop Implementation

Machine ID Generation

// Example: Generate unique machine ID
function getMachineId() {
  // Combine multiple hardware identifiers
  const cpuId = os.cpus()[0].model;
  const hostname = os.hostname();
  const networkInterfaces = os.networkInterfaces();
  const macAddress = Object.values(networkInterfaces)
    .flat()
    .find(i => !i.internal && i.mac !== '00:00:00:00:00:00')?.mac;
  
  // Create a hash of the combined values
  return crypto.createHash('sha256')
    .update(cpuId + hostname + macAddress)
    .digest('hex');
}

License Validation Flow

class LicenseManager {
  constructor(apiUrl, productCode) {
    this.apiUrl = apiUrl;
    this.productCode = productCode;
    this.machineId = getMachineId();
  }

  async validateLicense(licenseKey) {
    try {
      const response = await fetch(`${this.apiUrl}/api/v1/validate`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          licenseKey,
          productCode: this.productCode,
          machineId: this.machineId,
          requireActivation: true
        })
      });

      const result = await response.json();
      
      if (result.status === 'valid') {
        // Store validation result locally
        this.storeValidation(result);
        return { success: true, features: result.features };
      } else {
        return { success: false, error: result.message };
      }
    } catch (error) {
      // Fallback to offline validation if stored
      return this.offlineValidation(licenseKey);
    }
  }

  storeValidation(result) {
    // Encrypt and store for offline use
    const encrypted = encrypt(JSON.stringify({
      ...result,
      validatedAt: new Date().toISOString(),
      machineId: this.machineId
    }));
    localStorage.setItem('license_cache', encrypted);
  }

  offlineValidation(licenseKey) {
    // Check cached validation
    const cached = localStorage.getItem('license_cache');
    if (!cached) return { success: false, error: 'No cached license' };
    
    const decrypted = JSON.parse(decrypt(cached));
    const hoursSinceValidation = 
      (new Date() - new Date(decrypted.validatedAt)) / 1000 / 60 / 60;
    
    // Allow 72 hours offline grace period
    if (hoursSinceValidation < 72 && decrypted.licenseKey === licenseKey) {
      return { success: true, features: decrypted.features };
    }
    
    return { success: false, error: 'Offline validation expired' };
  }
}

Periodic Revalidation

Set up periodic validation checks:

// Validate on startup
await licenseManager.validateLicense(userLicenseKey);

// Revalidate every 24 hours
setInterval(async () => {
  const result = await licenseManager.validateLicense(userLicenseKey);
  if (!result.success) {
    // Handle license expiration or invalidation
    showLicenseError(result.error);
  }
}, 24 * 60 * 60 * 1000);
API Response Handling

Success Response

{
  "status": "valid",
  "message": "License is valid",
  "expiresAt": "2024-12-31T23:59:59Z",
  "features": ["basic", "advanced"],
  "customer": {
    "name": "Acme Corp",
    "email": "[email protected]"
  },
  "activations": {
    "used": 2,
    "limit": 5
  }
}

Error Responses

// Expired license
{
  "status": "expired",
  "message": "License expired on 2024-01-01",
  "expiresAt": "2024-01-01T00:00:00Z"
}

// Machine limit exceeded
{
  "status": "machine_limit_exceeded",
  "message": "Maximum activations reached",
  "activations": {
    "used": 5,
    "limit": 5
  }
}

Status Codes

StatusHTTP CodeDescription
valid200License is valid and active
expired403License has expired
blocked403License is suspended or blocked
invalid_product404Product code not found
rate_limited429Too many requests
Security Best Practices

Never expose license keys in client-side code

Always validate licenses server-side for web applications

Implement offline grace periods

Allow 24-72 hours of offline usage for desktop applications

Cache validation results

Reduce API calls by caching results for 5-15 minutes

Use HTTPS for all API calls

Ensure all license validation traffic is encrypted

Handle rate limits gracefully

Implement exponential backoff for retries

SDKs & Examples

Node.js SDK

Full-featured SDK for Node.js applications

Python SDK

Python library with async support

C# SDK

.NET SDK for desktop and server apps

REST Examples

cURL and Postman collection