✨ Qlipper

🔐 License API

Integrate licensing into your digital products

📊 Admin Dashboard
API v1.0
Base URL: https://license.qlipper.id

📖 What is Qlipper Licensing?

Qlipper provides a complete licensing system for desktop applications. Users purchase licenses and activate them on up to 2 devices. Your app verifies licenses when it starts.

👤 For Users

  • Purchase a license at Scalev
  • Receive license key via email
  • Register at member.qlipper.id
  • Activate license on their devices

💻 For Your App

  • Call verify endpoint on startup
  • Check if license is valid
  • Load paid features if valid
  • Show login page if not valid

🛒 For You

  • Users pay through Scalev
  • Webhook auto-generates licenses
  • Welcome email sent automatically
  • No manual license management

🔄 How It Works

  1. User purchases → Scalev sends webhook to our API
  2. License created → System generates unique license key
  3. Email sent → User receives license key automatically
  4. User registers → Goes to member.qlipper.id and creates account
  5. Activates license → Links license to their device(s)
  6. App verifies → Your app checks license on startup
  7. Features unlocked → Paid features become available
⚡ Key Facts:
  • Each license can be activated on maximum 2 devices
  • License keys look like: QLIP-3a9f2c-b81e04-c55d71
  • Users manage licenses at https://member.qlipper.id
  • Your app should verify license on startup only (not every action)
  • If offline, use cached verification (1-24 hours)

🚀 Quick Start

⚡ For Desktop/Desktop Apps (Qlipper AI)

When your app starts, immediately call the license verification endpoint to check if the user's license is valid:

const licenseKey = localStorage.getItem('qlipper_license_key'); const deviceId = getDeviceFingerprint(); // Your hardware ID fetch(`https://license.qlipper.id/license/verify?key=${licenseKey}&fingerprint=${deviceId}`) .then(res => res.json()) .then(data => { if (data.valid) { console.log('License valid! Tier:', data.tier); loadPaidFeatures(); } else { console.log('License invalid:', data.reason); redirectToLoginPage(); } });

Features

✓ License Verification

Instantly verify if a license is valid and active

✓ Device Binding

Limit licenses to 2 devices max per user

✓ Tier Support

Expandable tier system (Free, Paid, Enterprise)

✓ Auto Email

Automatic welcome email on purchase

📡 Public API Endpoints

GET /license/verify

Verify a license key on a device (PUBLIC - No Auth Required)

Query Parameters

Parameter Type Required Description
key String Yes License key (e.g., QLIP-3a9f2c-b81e04-c55d71)
fingerprint String Yes Device hardware fingerprint/ID

Response (200 - Valid)

{ "valid": true, "tier": 1 }

Response (200 - Invalid)

{ "valid": false, "reason": "key_not_found" | "device_not_activated" | "key_revoked" }

Example Request

curl "https://license.qlipper.id/license/verify?key=QLIP-3a9f2c-b81e04-c55d71&fingerprint=macbook-pro-2024"
POST /license/activate

Activate a license on a device (PUBLIC - No Auth Required)

Request Body

{ "key": "QLIP-3a9f2c-b81e04-c55d71", "fingerprint": "macbook-pro-2024", "label": "MacBook Pro" // Optional device name }

Response (200 - Success)

{ "success": true, "tier": 1, "devicesUsed": 1, "devicesMax": 2 }

Response (400 - Error)

{ "success": false, "reason": "max_devices_reached" | "key_invalid" | "already_activated" | "key_revoked" }

Example Request

curl -X POST https://license.qlipper.id/license/activate \ -H "Content-Type: application/json" \ -d '{ "key": "QLIP-3a9f2c-b81e04-c55d71", "fingerprint": "macbook-pro-2024", "label": "MacBook Pro" }'
POST /license/deactivate

Deactivate a license on a device (PROTECTED - JWT Required)

Request Body

{ "key": "QLIP-3a9f2c-b81e04-c55d71", "fingerprint": "macbook-pro-2024" }

Headers

Authorization: Bearer {jwt_token}

Response (200 - Success)

{ "success": true, "devicesUsed": 0, "devicesMax": 2 }

🔑 Authentication & User Management

POST /auth/register

Create an account (Email must be whitelisted)

Request Body

{ "email": "user@example.com", "password": "secure_password_123" }

Response (200)

{ "success": true, "token": "eyJhbGciOiJIUzI1NiIs...", "user": { "email": "user@example.com", "licenseKey": "QLIP-3a9f2c-b81e04-c55d71" } }
POST /auth/login

Login and get JWT token

Request Body

{ "email": "user@example.com", "password": "secure_password_123" }

Response (200)

{ "success": true, "token": "eyJhbGciOiJIUzI1NiIs...", "user": { "email": "user@example.com", "licenseKey": "..." }, "license": { "key": "...", "tier": 1, "status": "active", "devicesCount": 1 } }
GET /auth/me

Get current user info (PROTECTED - JWT Required)

Headers

Authorization: Bearer {jwt_token}

Response (200)

{ "success": true, "user": { "email": "user@example.com", "licenseKey": "QLIP-..." }, "license": { "key": "QLIP-3a9f2c-b81e04-c55d71", "tier": 1, "status": "active", "devices": [ { "fingerprint": "macbook-pro-2024", "label": "MacBook Pro", "activatedAt": "2026-02-19T10:30:00Z" } ] } }

👨‍💼 Admin Endpoints (Whitelist Management)

POST /admin/whitelist

Manually add a user (PROTECTED - Admin Secret Required)

Headers

X-Admin-Secret: sanwidiganja Content-Type: application/json

Request Body

{ "email": "newuser@example.com", "productName": "Qlipper AI", "tier": 1 }

Response (200)

{ "success": true, "key": "QLIP-a1b2c3-d4e5f6-g7h8i9", "email": "newuser@example.com" }

🔔 Webhooks (Scalev Integration)

POST /webhook/scalev

Receive purchase notifications from Scalev (PUBLIC)

Scalev Configuration

In your Scalev dashboard, add this webhook URL:

https://license.qlipper.id/webhook/scalev

Expected Webhook Payload (from Scalev)

{ "scalevOrderId": "order-123456", "email": "buyer@example.com", "productName": "Qlipper AI", "amount": 49.99 }

Response (200)

{ "success": true, "key": "QLIP-3a9f2c-b81e04-c55d71", "email": "buyer@example.com" }

⚡ What Happens Automatically

  1. Scalev sends purchase data to our webhook
  2. We generate a license key for the buyer
  3. Email sent automatically with license key + link to member.qlipper.id
  4. Buyer registers account and activates license

📱 Desktop App Integration Guide

Step 1: Get Device Fingerprint

Generate a unique hardware ID for the device:

// Python example import hashlib import platform import uuid def get_device_fingerprint(): # Combine CPU ID, OS info, and machine name data = f"{platform.machine()}-{platform.processor()}-{uuid.getnode()}" return hashlib.sha256(data.encode()).hexdigest()[:24] device_id = get_device_fingerprint() # Example: "a1b2c3d4e5f6g7h8i9j0k1l2"

Step 2: Store & Retrieve License Key

// Store in local config/database config.qlipper_license_key = "QLIP-3a9f2c-b81e04-c55d71" config.device_fingerprint = get_device_fingerprint()

Step 3: Verify License on App Startup

import requests def verify_license(): key = config.get('qlipper_license_key') device_id = config.get('device_fingerprint') if not key or not device_id: return False try: response = requests.get( 'https://license.qlipper.id/license/verify', params={'key': key, 'fingerprint': device_id}, timeout=5 ) data = response.json() if data['valid']: print(f"✓ License valid! Tier: {data['tier']}") return True else: print(f"✗ License invalid: {data['reason']}") return False except Exception as e: print(f"⚠ License check failed: {e}") # For offline mode, allow access (will verify when online again) return True if __name__ == '__main__': if verify_license(): load_app() else: show_license_invalid_screen()

Step 4: Activate License (First Time)

import requests def activate_license(license_key): device_id = get_device_fingerprint() response = requests.post( 'https://license.qlipper.id/license/activate', json={ 'key': license_key, 'fingerprint': device_id, 'label': f'Qlipper {platform.system()}' }, timeout=10 ) data = response.json() if data['success']: config.save({ 'qlipper_license_key': license_key, 'device_fingerprint': device_id }) print("✓ License activated!") return True else: print(f"✗ Activation failed: {data['reason']}") return False

Step 5: Handle License States

# In your app initialization: if not verify_license(): # Show license invalid / expired screen show_modal( title="License Invalid", message="Your license is not valid or inactive.", action="Open License Manager", url="https://member.qlipper.id" ) else: # Load full app load_paid_features()

⚠️ Error Codes & Responses

Reason Code HTTP Status Meaning User Action
key_not_found 200 License key doesn't exist User needs to purchase
device_not_activated 200 Key exists but not activated on this device User must activate license first
key_revoked 200 License was revoked/cancelled User must contact support
max_devices_reached 400 Already activated on 2 devices (limit) Deactivate on another device first
already_activated 200 This device is already activated No action needed

⚡ Best Practices

✓ Do

  • Cache license verification (1-24 hours)
  • Verify on app startup
  • Allow offline access (verify when online)
  • Use HTTPS only
  • Handle network timeouts gracefully
  • Store device fingerprint securely

✗ Don't

  • Verify on every action (performance)
  • Store license key in plain text
  • Send license key in URLs
  • Trust client-side verification only
  • Expose device fingerprinting logic
  • Log full license keys

📞 Support

Need help integrating? Issues with the API?

Email: widi.adyatma@gmail.com
API Status: All Systems Operational