Skip to main content

Python SDK for the Licentric software licensing API

Project description

Licentric Python SDK

License: MIT

Official Python client for the Licentric software licensing API. Validate licenses, manage machine activations, send heartbeats, and check out offline license files.

Note: This package is not yet published to PyPI. Install from source (see below).

Installation

# Install from source (not yet published to PyPI)
cd sdks/python
pip install -e .

Requirements: Python 3.9+

Quick Start

from licentric import Licentric

client = Licentric(api_key="lk_live_...")

# Validate a license key
result = client.validate(key="LIC-XXXX-XXXX-XXXX")
if result.valid:
    print(f"License is valid — code: {result.code}")

Machine Activation

from licentric import Licentric
from licentric.fingerprint import fingerprint

client = Licentric(api_key="lk_live_...")

# Activate a machine
machine = client.activate(
    key="LIC-XXXX-XXXX-XXXX",
    fingerprint=fingerprint(),
    name="production-server",
    platform="linux",
)
print(f"Activated machine: {machine.id}")

# Send heartbeat to keep the machine alive
client.heartbeat(machine_id=machine.id, key="LIC-XXXX-XXXX-XXXX")

# Deactivate when done
client.deactivate(machine_id=machine.id, key="LIC-XXXX-XXXX-XXXX")

Fetching License Details

get_license and get_license_by_key return the full license — including all activated machines and the bound policy snapshot — in a single API call. Useful for dashboards, admin UIs, and any flow that needs to inspect the ruleset without making three sequential requests.

client = Licentric(api_key="lk_live_...")

# By internal license ID
license = client.get_license("lic_abc123")

# Or by raw license key (URL-encoded server-side)
license = client.get_license_by_key("LIC-XXXX-XXXX-XXXX-XXXX")

print(f"Status: {license.status}")
print(f"Active machines: {len(license.machines or [])}")
print(f"Max machines allowed: {license.policy.max_machines}")
print(f"Offline allowed: {license.policy.offline_allowed}")
print(f"Feature flags: {license.policy.metadata.get('feature_flags', [])}")

The raw key and key_hash fields are stripped server-side — License returned here never contains the secret material.

Offline License Files

Check out a signed license file for offline validation:

license_file = client.checkout(
    license_id="uuid-of-license",
    fingerprint=fingerprint(),
    ttl=1209600,  # 14 days
)
print(f"Certificate: {license_file.certificate}")

Offline Caching

Cache validation results locally with HMAC-SHA256 tamper detection:

from licentric.cache import ValidationCache

cache = ValidationCache()

# Store a validation result (default TTL: 15 minutes)
cache.set(key_hash="sha256_of_license_key", result={"valid": True, "code": "VALID"})

# Retrieve (returns None if expired or tampered)
cached = cache.get(key_hash="sha256_of_license_key")
if cached:
    print(cached.data)

Error Handling

All API errors inherit from LicentricError with structured fields:

from licentric import (
    Licentric,
    AuthenticationError,
    LicenseRevokedError,
    LicenseSuspendedError,
    LicenseExpiredError,
    NotFoundError,
    RateLimitError,
)
import time

client = Licentric(api_key="lk_live_...")

try:
    machine = client.activate(key="LIC-XXXX", fingerprint="abc123")
except LicenseRevokedError:
    # Permanent — show "license has been revoked, contact support"
    print("License revoked")
except LicenseSuspendedError:
    # Temporary — usually a payment issue; surface "billing on hold"
    print("License suspended")
except LicenseExpiredError:
    # Renewal flow
    print("License expired — please renew")
except RateLimitError as e:
    # Retry-eligible after backoff
    time.sleep(e.retry_after)
except AuthenticationError:
    # Configuration problem — fail immediately
    print("Invalid API key")

HTTP-status exceptions (raised by HTTP code)

Exception HTTP Status When
AuthenticationError 401 Invalid or missing API key
ForbiddenError 403 Authenticated but lacks permission/scope
NotFoundError 404 Resource does not exist
ValidationError 400 Invalid request parameters (details has Zod issues)
ConflictError 409 Generic state conflict (no specific license-state code)
RateLimitError 429 Too many requests (use retry_after)
LicentricError 5xx + other Base class — also raised for unknown statuses

License-state exceptions (raised by body code, regardless of HTTP status)

These subclass LicentricError directly — NOT the HTTP-status classes — so catching ConflictError will NOT catch them. Catch by license-state class explicitly:

Exception API code When
LicenseRevokedError LICENSE_REVOKED License has been revoked (permanent)
LicenseSuspendedError LICENSE_SUSPENDED License is suspended (e.g. payment failure — temporary)
LicenseExpiredError LICENSE_EXPIRED License past expiration and policy disallows continued use
LicenseBannedError LICENSE_BANNED License banned for abuse (terminal — no recovery)

Recovery classification — what to retry vs fail immediately

Strategy Exceptions
Grace-eligible (use cached validation if available, retry on next request) Network errors, 5xx LicentricError, RateLimitError after backoff completes
Fail immediately (do not retry; surface to end user) LicenseRevokedError, LicenseSuspendedError, LicenseExpiredError, LicenseBannedError, AuthenticationError, NotFoundError, ValidationError

API Reference

Licentric(api_key, base_url?, timeout?)

Parameter Type Default Description
api_key str Your API key (lk_live_... or lk_test_...)
base_url str https://licentric.com API base URL
timeout float 30.0 Request timeout in seconds

Methods

Method Auth Description
validate(key, fingerprint?, entitlements?) License key Validate a license key
activate(key, fingerprint, name?, platform?) License key Activate a machine
deactivate(machine_id, key) License key Remove a machine activation
heartbeat(machine_id, key) License key Send a machine heartbeat
checkout(license_id, fingerprint, ttl?) API key Check out an offline license file
close() Close the HTTP client

The client supports context manager usage:

with Licentric(api_key="lk_live_...") as client:
    result = client.validate(key="LIC-XXXX-XXXX-XXXX")

Machine Fingerprinting

The fingerprint() function generates a stable SHA-256 hash identifying the current machine:

Platform Source
macOS Hardware UUID via ioreg
Linux /etc/machine-id or Docker container ID
Windows Product UUID via wmic
Fallback hostname:username hash

Type Safety

This package includes a py.typed marker (PEP 561) and ships with full type annotations. Works with mypy, pyright, and other type checkers out of the box.

Documentation

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

licentric-0.1.0.tar.gz (39.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

licentric-0.1.0-py3-none-any.whl (20.4 kB view details)

Uploaded Python 3

File details

Details for the file licentric-0.1.0.tar.gz.

File metadata

  • Download URL: licentric-0.1.0.tar.gz
  • Upload date:
  • Size: 39.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for licentric-0.1.0.tar.gz
Algorithm Hash digest
SHA256 301e10612f1ec9e10f441e416e1c7eb31521e4de2571db94524bd629f3a990c8
MD5 2cc495e3a5313fea6ea549d68f38c4f7
BLAKE2b-256 07d441f48f4f218903508238b21960c03579b88c7758a199e88f0c489ffbf7cb

See more details on using hashes here.

File details

Details for the file licentric-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: licentric-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 20.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for licentric-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 23815470c112c7f1eb25ece6709e0ba0d9a81ba7411b8fda1c0697c45154b6ea
MD5 629ea5be29fca6678b1b82cf30fb166c
BLAKE2b-256 f798ec494b5fcd3bd431692e2d0cdab92b0009eaaf1b8b4d8b547fcc3fa5bc20

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page