Guides
SaaS Product Licensing
Validate licenses server-side with session management and automatic provisioning via Stripe.
saas policy template: unlimited devices, daily heartbeat, transferable, no fingerprint required.1. Create Product and Policy
SaaS products use floating licenses with no device limits. Heartbeats ensure active usage tracking.
from licentric import Licentric
client = Licentric(api_key="lk_live_your_key_here")
product = client.products.create(
name="My SaaS Platform",
code="SAAS"
)
policy = client.policies.create(
name="SaaS Subscription",
product_id=product.id,
template="saas" # Unlimited devices, heartbeat, transferable
)2. Validate on Login
Validate the license once when the user logs in and store the result in their session. No fingerprint is needed for SaaS — use the license key alone.
Python
from licentric import Licentric
client = Licentric(api_key="lk_live_your_key_here")
def validate_on_login(license_key: str, user_id: str) -> bool:
"""Validate the license when a user logs in."""
result = client.validate(key=license_key)
if not result.valid:
return False
# Store validation result in session
session = get_session(user_id)
session["license_valid"] = True
session["license_id"] = result.license_id
session["entitlements"] = result.entitlements
session.save()
return TrueTypeScript
import { Licentric } from "@licentric/sdk";
const client = new Licentric({ apiKey: "lk_live_your_key_here" });
async function validateOnLogin(
licenseKey: string,
userId: string
): Promise<boolean> {
const result = await client.validate({ key: licenseKey });
if (!result.valid) {
return false;
}
// Store validation result in session
const session = await getSession(userId);
session.licenseValid = true;
session.licenseId = result.licenseId;
session.entitlements = result.entitlements;
await session.save();
return true;
}3. Protect Routes with Middleware
Use middleware to check the session for a valid license on each request. This avoids re-validating against the API on every page load.
def require_valid_license(handler):
"""Middleware: check session for valid license on each request."""
def wrapper(request):
session = get_session(request.user_id)
if not session.get("license_valid"):
return Response(status=403, body={
"error": "No valid license. Please subscribe."
})
return handler(request)
return wrapper
# Usage
@require_valid_license
def dashboard_handler(request):
return render_dashboard(request)4. Send Heartbeats
The SaaS template enables heartbeats by default. Send a heartbeat periodically to confirm the license is actively in use. If a heartbeat is missed, validation returns HEARTBEAT_REQUIRED.
# The SaaS template enables heartbeats by default.
# Heartbeats ensure licenses are actively in use.
#
# Server-side: send heartbeat on each authenticated request
# (or on a schedule, e.g., every 30 minutes)
def send_heartbeat(license_id: str, machine_id: str):
"""Ping Licentric to confirm active usage."""
client.machines.heartbeat(
license_id=license_id,
machine_id=machine_id
)5. Pair with Stripe
For the best SaaS experience, connect Stripe to automatically provision licenses when customers subscribe. See the Stripe Integration guide for full setup.
# When a Stripe checkout completes, Licentric automatically:
# 1. Creates a customer (if not exists)
# 2. Issues a license key
# 3. Sends the key via webhook to your app
#
# Your webhook handler:
def handle_license_created(event):
license = event["data"]
user = find_user_by_email(license["email"])
user.license_key = license["key"]
user.save()
send_welcome_email(user)