Skip to content

🔐 Multi-Product Licensing Guide

📋 Overview

The PenguinTech licensing system supports multiple products under a single license key. This allows customers to purchase one license that covers Tobogganing, SquawkDNS, WaddleBot, and future products at different tiers.

🎯 Product Portfolio

🦭 Tobogganing (VPN/SASE)

  • Community: Core VPN features, unlimited clients/headends
  • Professional: Adds metrics, advanced firewall, VRF/OSPF
  • Enterprise: Adds SSO, LDAP, MFA, traffic mirroring, custom branding

🦆 SquawkDNS (DNS Filtering)

  • Community: Basic DNS filtering, unlimited queries
  • Professional: Advanced filtering, analytics, custom blocklists
  • Enterprise: Threat intelligence, centralized management, SSO

🤖 WaddleBot (Chat Bot)

  • Community: Basic chat commands, single server
  • Professional: Multi-server, cloud storage, analytics
  • Enterprise: Custom integrations, SSO, audit logging

🚀 Future Products

  • Additional products will be added to the same licensing system
  • Customers can upgrade individual products or add new ones to existing licenses

🔑 License Key Format

License keys work across all products:

PENG-XXXX-XXXX-XXXX-XXXX-YYYY

Where: - PENG - PenguinTech product identifier - XXXX - Random alphanumeric segments
- YYYY - Checksum for validation

Example: PENG-A1B2-C3D4-E5F6-G7H8-9IJK

📊 Multi-Product License Examples

Basic Bundle

{
  "license_key": "PENG-A1B2-C3D4-E5F6-G7H8-9IJK",
  "customer": "Acme Corp",
  "products": {
    "tobogganing": "community",
    "squawkdns": "professional"
  }
}

Enterprise Bundle

{
  "license_key": "PENG-ENT1-ERPX-2024-PROD-ABC1",
  "customer": "Enterprise Inc",
  "products": {
    "tobogganing": "enterprise",
    "squawkdns": "enterprise", 
    "waddlebot": "professional"
  }
}

🔌 API Integration

Universal Validation Endpoint

All products use the same validation endpoint:

POST https://license.penguintech.io/api/validate
Content-Type: application/json

{
  "license_key": "PENG-A1B2-C3D4-E5F6-G7H8-9IJK",
  "product": "tobogganing"
}

Response:

{
  "valid": true,
  "product": "tobogganing",
  "tier": "professional",
  "features": [
    "wireguard_vpn",
    "client_metrics",
    "prometheus_export",
    "advanced_firewall"
  ],
  "all_products": {
    "tobogganing": "professional",
    "squawkdns": "enterprise"
  },
  "expires_at": "2025-12-31T23:59:59Z"
}

Feature Check Endpoint

POST https://license.penguintech.io/api/check_feature
Content-Type: application/json

{
  "license_key": "PENG-A1B2-C3D4-E5F6-G7H8-9IJK",
  "product": "tobogganing",
  "feature": "client_metrics"
}

Response:

{
  "enabled": true,
  "product": "tobogganing",
  "tier": "professional",
  "message": "Feature enabled"
}

💻 Product Integration Examples

Tobogganing Integration

import requests

def check_tobogganing_license():
    response = requests.post(
        'https://license.penguintech.io/api/validate',
        json={
            'license_key': os.getenv('LICENSE_KEY'),
            'product': 'tobogganing'
        }
    )

    if response.status_code == 200:
        data = response.json()
        if data['valid']:
            return {
                'tier': data['tier'],
                'features': data['features'],
                'expires_at': data['expires_at']
            }

    return {'tier': 'community', 'features': get_community_features()}

SquawkDNS Integration

def check_squawkdns_feature(feature):
    response = requests.post(
        'https://license.penguintech.io/api/check_feature',
        json={
            'license_key': os.getenv('LICENSE_KEY'),
            'product': 'squawkdns',
            'feature': feature
        }
    )

    if response.status_code == 200:
        return response.json()['enabled']

    # Default to community features
    community_features = ['dns_server', 'basic_filtering', 'unlimited_queries']
    return feature in community_features

WaddleBot Integration

const checkWaddleBotLicense = async () => {
  try {
    const response = await fetch('https://license.penguintech.io/api/validate', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        license_key: process.env.LICENSE_KEY,
        product: 'waddlebot'
      })
    });

    const data = await response.json();
    return data.valid ? data : { tier: 'community' };
  } catch (error) {
    return { tier: 'community' }; // Fallback to community
  }
};

🛒 License Management

Sales Team Features

The license server provides management capabilities for creating multi-product licenses:

# Create multi-product license
license_data = {
    'customer_name': 'Enterprise Corp',
    'customer_email': '[email protected]',
    'organization': 'Enterprise Corp',
    'products': {
        'tobogganing': 'enterprise',
        'squawkdns': 'professional',
        'waddlebot': 'community'
    },
    'expires_at': datetime(2025, 12, 31),
    'notes': 'Enterprise bundle with custom Tobogganing tier'
}

Product Addition

Add new products to existing licenses:

# Add WaddleBot to existing Tobogganing license
existing_license.products['waddlebot'] = 'professional'

Tier Upgrades

Upgrade individual products:

# Upgrade SquawkDNS from professional to enterprise
license.products['squawkdns'] = 'enterprise'

📈 Pricing Strategy

Individual Products

  • Community: Free (all products)
  • Professional: $99/month per product
  • Enterprise: $299/month per product

Bundle Discounts

  • 2 Products: 15% discount
  • 3+ Products: 25% discount
  • Enterprise Bundle: Custom pricing

Example Pricing

Single Product Professional: $99/month
Two Product Bundle:         $168/month (15% off)
Three Product Bundle:       $222/month (25% off)
Enterprise Bundle:          Contact sales

🔍 Troubleshooting

License Not Found for Product

# Check what products are available in your license
curl -X POST https://license.penguintech.io/api/validate \
  -H "Content-Type: application/json" \
  -d '{"license_key": "YOUR-LICENSE", "product": "tobogganing"}'

# Response will show available_products if product not found
{
  "valid": false,
  "message": "Product 'waddlebot' not included in this license",
  "available_products": ["tobogganing", "squawkdns"]
}

Feature Not Available

# Check if feature requires higher tier
curl -X POST https://license.penguintech.io/api/check_feature \
  -H "Content-Type: application/json" \
  -d '{
    "license_key": "YOUR-LICENSE",
    "product": "tobogganing", 
    "feature": "sso_authentication"
  }'

Legacy Endpoint Support

Old endpoints still work for backward compatibility: - POST /api/tobogganing/validate → redirects to /api/validate - POST /api/tobogganing/check_feature → redirects to /api/check_feature

🔐 Security Features

License Validation

  • Server-side validation: All checks happen on license.penguintech.io
  • Caching: Products cache validation for 1 hour to reduce API calls
  • Fallback: Products gracefully fall back to community features if license server unreachable
  • Audit trail: All validations are logged for compliance

Rate Limiting

  • Per-license limits: Prevent abuse of validation endpoints
  • IP-based limits: Protect against brute force attacks
  • Graduated responses: Temporary blocks for suspicious activity

📝 Migration Guide

From Single-Product to Multi-Product

Old Tobogganing validation:

# Old way (still works)
response = requests.post(
    'https://license.penguintech.io/api/tobogganing/validate',
    json={'license_key': LICENSE_KEY}
)

New multi-product validation:

# New way (recommended)
response = requests.post(
    'https://license.penguintech.io/api/validate',
    json={
        'license_key': LICENSE_KEY,
        'product': 'tobogganing'
    }
)

Database Schema Migration

Sales teams need to migrate existing licenses:

-- Old schema had single product/tier
-- New schema uses JSON products field

UPDATE licenses 
SET products = JSON_OBJECT(
  COALESCE(product, 'squawkdns'), 
  COALESCE(license_tier, 'basic')
)
WHERE products IS NULL;