Skip to main content

Client SDK for PyLicense — verify software license keys with tamper-proof, signed responses.

Project description

pylicensify

Client SDK for PyLicense — verify software license keys with tamper-proof, signed responses. A cracked "fake server" can't grant access, because every response is verified against your public key.

pip install pylicensify

Quick start

Get your public key from the dashboard → Integration page (safe to embed in your distributed app; the private key never leaves the server).

from pylicensify import LicenseClient

client = LicenseClient(public_key="YOUR_PUBLIC_KEY")

result = client.validate("PY-XXXXXXXXXXXXXXXX")
if result:
    print("Licensed. Entitlements:", result.features)
    if result.feature("pro"):
        enable_pro_features()
else:
    print("Not licensed:", result.error)
    raise SystemExit(1)

validate() sends a nonce, verifies the Ed25519 signature, and rejects stale / replayed responses automatically. It raises SignatureError on tampering and NetworkError if the server is unreachable.

Feature gating

result = client.validate(key)
seats = result.feature("seats", 1)
if result.feature("pro"):
    ...

Offline license files (air-gapped)

Issue a signed .lic file from a license row in the dashboard, ship it with the app, and verify it locally with zero network calls:

from pylicensify import verify_offline_license

data = verify_offline_license("YOUR_PUBLIC_KEY", "license.lic")
print("Valid for:", data.get("customer"), data.get("features"))

Checks signature, expiry, device binding, and OS lock.

Floating / concurrent licenses

For keys with a concurrent-session limit — the SDK checks out a seat, heartbeats in the background, and releases on exit:

from pylicensify import LicenseClient, SeatUnavailable

client = LicenseClient(public_key="YOUR_PUBLIC_KEY")
try:
    with client.session("PY-XXXX...") as sess:
        print("Seat acquired:", sess.seats)   # {'used': 1, 'max': 5}
        run_app()                              # released automatically on exit
except SeatUnavailable:
    print("All seats are in use — try again later.")

Update checks

info = client.check_update("PY-XXXX...", current_version="1.0.0")
if info["update_available"]:
    print("New version:", info["version"], info["notes"])
    # info["download_url"] is a license-gated download link

Self-hosted / custom domain

client = LicenseClient(public_key="...", api_url="https://license.yourdomain.com")

Hardware ID

By default the SDK derives a machine id from uuid.getnode(). Pass your own for a stronger fingerprint:

client.validate(key, hwid=my_custom_fingerprint())

Errors

Exception Meaning
InvalidLicense Server rejected the key (invalid/expired/revoked/blocked)
SignatureError Signature/nonce/timestamp failed — forged or replayed
NetworkError Couldn't reach the license server
SeatUnavailable Floating license has no free seats

All inherit from LicenseError.

Hardening

Obfuscate your client so the check itself can't be trivially patched out — e.g. with PyObfuscate.

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

pylicensify-1.0.0.tar.gz (8.0 kB view details)

Uploaded Source

Built Distribution

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

pylicensify-1.0.0-py3-none-any.whl (8.0 kB view details)

Uploaded Python 3

File details

Details for the file pylicensify-1.0.0.tar.gz.

File metadata

  • Download URL: pylicensify-1.0.0.tar.gz
  • Upload date:
  • Size: 8.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for pylicensify-1.0.0.tar.gz
Algorithm Hash digest
SHA256 2e9ecd0ca05c56c0d19648de68ee907de6d26f3c5eb6b34ba314a47c70d902c5
MD5 2c854aff5ecc274a0d6ad3fc9970e919
BLAKE2b-256 e0ff39436b77c3311d8704a257c3db912603dbb47cbef77a9286f967128cf864

See more details on using hashes here.

File details

Details for the file pylicensify-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: pylicensify-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 8.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for pylicensify-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e192ed7cb424fb8a5c9098f94738567c6a8455fcf97d6331cd0ffaae52121d2d
MD5 d64823edb3af2156a6319b5c45a70125
BLAKE2b-256 8b90a6e48bb0a119cfadc66108862679de9fa89eb2b497061491c22d577db157

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