Generated public API¶
Generated from the installed source docstrings, not a second API implementation. Use Configuration and the tested source examples for setup.
Manage one stable installation and its signed access state.
Mutating/check operations serialize across clients/processes sharing the same local directory. Use a private local filesystem, not NFS. HTTPS is required; allow_loopback_http is an explicit local-test-only opt-in. The default environment remains LIVE for compatibility; use SANDBOX in tests.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
product
|
str
|
Public App ID from the platform, never a developer API key. |
required |
environment
|
str
|
LIVE or SANDBOX; production/test are accepted aliases. |
'production'
|
base_url
|
str
|
HTTPS site origin without a path, credentials or query. |
'https://licensing.kdpika.com'
|
application_name
|
str
|
Your app name; also determines the default state folder. |
'Licensed Application'
|
application_version
|
str
|
Your software version sent during activation. |
''
|
verification_key
|
dict[str, str] | None
|
Optional pinned key_id/public_key dictionary. Ed25519 and base64url only; the ID must match the public-key hash. |
None
|
storage_dir
|
Path | None
|
Persistent private root; the SDK adds a product/environment namespace. |
None
|
timeout
|
float
|
Default transport socket timeout in seconds, greater than 0 and at most 120. |
15.0
|
prefer_keyring
|
bool
|
Try an available optional OS keyring before private files. |
True
|
transport
|
Transport | None
|
Advanced trusted transport injection; private protocol, no verification bypass. |
None
|
clock
|
Callable[[], datetime] | None
|
Injectable aware datetime provider; normal apps should keep the UTC default. |
None
|
allow_loopback_http
|
bool
|
Explicit local testing opt-in, never for remote HTTP. |
False
|
Attributes:
| Name | Type | Description |
|---|---|---|
product |
Normalized configured Public App ID. |
|
environment |
Normalized LIVE or SANDBOX name. |
|
base_url |
Configured API origin. |
|
application_name |
Descriptive app name. |
|
application_version |
Descriptive app version. |
|
installation_id |
Persisted random identity. Preserve it across launches/upgrades. |
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
Invalid origin, environment, product, timeout or pin. |
StorageError
|
State/identity cannot be initialized safely. |
Examples:
Create temporary Sandbox state without making a network request:
>>> from tempfile import TemporaryDirectory
>>> from pathlib import Path
>>> with TemporaryDirectory() as directory:
... client = LicenseClient("app_synthetic", environment="SANDBOX",
... storage_dir=Path(directory), prefer_keyring=False)
... print(client.check().error_code)
NOT_ACTIVATED
activated: bool
property
¶
Whether a token is stored; never use this as an access decision.
storage_security: str
property
¶
Report keyring or file storage; this is not an OS security certification.
__init__(product: str, environment: str = 'production', base_url: str = 'https://licensing.kdpika.com', application_name: str = 'Licensed Application', application_version: str = '', verification_key: dict[str, str] | None = None, storage_dir: Path | None = None, timeout: float = 15.0, prefer_keyring: bool = True, transport: Transport | None = None, clock: Callable[[], datetime] | None = None, *, allow_loopback_http: bool = False) -> None
¶
activate(license_key: str, email: str | None = None) -> LicenseResult
¶
Activate this persistent installation online.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
license_key
|
str
|
Customer key obtained privately, never logged. |
required |
email
|
str | None
|
Customer email when the product's policy requires a match. |
None
|
Returns:
| Type | Description |
|---|---|
LicenseResult
|
Signed access decision, or an invalid result with a stable error code. |
LicenseResult
|
HTTP refusals/network/storage failures never grant features. |
Examples:
See the tested examples/basic.py and examples/session.py scripts. Require result.valid and result.signature_valid before protected work.
check(force_online: bool = False) -> LicenseResult
¶
Check current access from verified cache or the service.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
force_online
|
bool
|
Request fresh validation rather than an ordinary cache hit. A transport failure can still use authentic unexpired signed grace. |
False
|
Returns:
| Type | Description |
|---|---|
LicenseResult
|
Current decision. An authoritative HTTP refusal never falls back to cache. |
validate() -> LicenseResult
¶
Request online validation, equivalent to check(force_online=True).
Returns:
| Type | Description |
|---|---|
LicenseResult
|
Fresh decision, or signed offline-grace decision on a network failure. This is not a strict online-only/payment-verification operation. |
deactivate() -> LicenseResult
¶
Release the server seat before clearing credentials; preserve identity.
Returns:
| Type | Description |
|---|---|
LicenseResult
|
valid=True only for a successful release acknowledgement. It has no |
LicenseResult
|
verified license signature and cannot enable features. Failure keeps |
LicenseResult
|
recovery state where safe; do not blindly retry an uncertain outcome. |
feature(name: str, default: bool = False) -> bool
¶
Re-check access and evaluate a boolean/numeric entitlement.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Feature key configured in the product's license plan. |
required |
default
|
bool
|
Missing-feature fallback only for a valid verified decision. |
False
|
Returns:
| Type | Description |
|---|---|
bool
|
False on any refused/unsigned/expired decision, regardless of default. |
feature_value(name: str, default: Any = None) -> Any
¶
Re-check access, then read an entitlement without interpreting its type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Configured feature/limit key. |
required |
default
|
Any
|
Missing-key fallback only while the decision authorizes access. |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
Detached entitlement value, or None on failure. Validate a numeric |
Any
|
value's type/range before using it as an application limit. |
reset_local() -> None
¶
Erase token/cache, preserving identity. This does NOT release a seat.
Raises:
| Type | Description |
|---|---|
StorageError
|
Locking, file cleanup or keyring deletion failed. |
Examples:
Prefer deactivate() first. Do not delete identity to bypass seat limits.
One verified decision, not a permanent grant or proof of payment.
Helpers re-evaluate time at use and deny on every invalid/unsigned result. payload remains readable for diagnostics, but is excluded from repr.
Attributes:
| Name | Type | Description |
|---|---|---|
valid |
bool
|
Decision at check time; not a permanent capability. |
source |
str
|
online, cache, offline or local decision origin. |
payload |
dict[str, Any]
|
Detached signed payload for private diagnostics, never logs. |
error_code |
str | None
|
Stable safe refusal code, or None. |
message |
str
|
SDK-owned display message; arbitrary constructed messages are not sanitized. |
request_id |
str | None
|
Bounded safe support identifier, or None. |
signature_valid |
bool
|
Whether the SDK authenticated the payload signature. |
storage_security |
str
|
os-keyring, permission-protected-file or unknown. |
Examples:
>>> result = LicenseResult(False, "local", error_code="NOT_ACTIVATED")
>>> result.feature("pdf_export", True)
False
>>> result.feature_value("seat_count", 100) is None
True
Constructing this dataclass is not signature verification. Obtain access decisions from LicenseClient, not user-provided dictionaries/booleans.
status: str
property
¶
Return the signed status, or unknown when absent.
license_id: str | None
property
¶
Return the license identifier, not a customer secret.
expires_at: str | None
property
¶
Return the original signed expiry string, or None for lifetime.
offline_grace_until: str | None
property
¶
Return the original signed absolute grace deadline.
features: dict[str, Any]
property
¶
Return a detached feature map only while the decision authorizes access.
feature(name: str, default: bool = False) -> bool
¶
Check a boolean/numeric flag on a currently authorized decision.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Configured feature key. |
required |
default
|
bool
|
Missing-key fallback for an authorized decision only. |
False
|
Returns:
| Type | Description |
|---|---|
bool
|
True for boolean True or a positive number. String values do not |
bool
|
enable a flag. Invalid decisions ignore enabling defaults. |
feature_value(name: str, default: Any = None) -> Any
¶
Read a detached value only while the decision authorizes access.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Configured feature/limit key. |
required |
default
|
Any
|
Missing-key fallback for an authorized decision only. |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
A copied entitlement, or None on failure regardless of default. |
Any
|
This does not validate whether a value is a usable numeric limit. |
Wrap a configured LicenseClient without duplicating cryptographic policy.
Calls use asyncio.to_thread. Cancelling the await does not cancel an in-flight HTTP mutation; its outcome may be uncertain. Reuse the same identity, inspect status, and never blindly retry activation/deactivation after cancellation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
LicenseClient
|
Already-configured synchronous client; no second installation is created. |
required |
Examples:
See examples/async_usage.py for a runnable environment-configured lifecycle. Require result.valid and result.signature_valid after every awaited check.
>>> import asyncio
>>> from pathlib import Path
>>> from tempfile import TemporaryDirectory
>>> with TemporaryDirectory() as directory:
... core = LicenseClient("app_synthetic", environment="SANDBOX",
... storage_dir=Path(directory), prefer_keyring=False)
... client = AsyncLicenseClient(core)
... print(asyncio.run(client.check()).error_code)
NOT_ACTIVATED
storage_security: str
property
¶
Report the synchronous core's selected storage backend.
__init__(client: LicenseClient) -> None
¶
is_activated() -> bool
async
¶
Check token presence without blocking the event loop; not an access grant.
activate(license_key: str, email: str | None = None) -> LicenseResult
async
¶
Activate using the synchronized core.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
license_key
|
str
|
Customer key obtained privately, never logged. |
required |
email
|
str | None
|
Optional email required by the server's product policy. |
None
|
Returns:
| Type | Description |
|---|---|
LicenseResult
|
The core's signed access decision or safe refusal. |
check(force_online: bool = False) -> LicenseResult
async
¶
Check current access without blocking the event loop.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
force_online
|
bool
|
Request validation; network failure may still use signed grace. |
False
|
Returns:
| Type | Description |
|---|---|
LicenseResult
|
The same fail-closed decision as LicenseClient.check. |
validate() -> LicenseResult
async
¶
Request fresh validation with the same signed-grace rules.
deactivate() -> LicenseResult
async
¶
Release the seat; a successful acknowledgement grants no features.
feature(name: str, default: bool = False) -> bool
async
¶
Re-check access and safely evaluate a flag.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Configured entitlement key. |
required |
default
|
bool
|
Missing-key fallback only on a valid verified decision. |
False
|
Returns:
| Type | Description |
|---|---|
bool
|
False on failure regardless of the default. |
feature_value(name: str, default: Any = None) -> Any
async
¶
Re-check access and safely read an entitlement.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Configured entitlement key. |
required |
default
|
Any
|
Missing-key fallback only on a valid verified decision. |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
A detached entitlement, or None on failure. |
reset_local() -> None
async
¶
Erase local token/cache, not the installation identity or server seat.
Raises:
| Type | Description |
|---|---|
StorageError
|
State locking or credential cleanup failed. |
Bases: Exception
Base safe SDK exception; most operational failures use LicenseResult.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
Accepted for compatibility but deliberately not retained. |
''
|
request_id
|
str | None
|
Optional bounded support identifier, never a credential. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
code |
Stable SDK exception code. |
|
request_id |
Sanitized support identifier or None. |
|
safe_message |
SDK-owned static human-readable message. |
Examples:
>>> error = StorageError(request_id="req_example")
>>> error.code
'STORAGE_ERROR'
>>> error.request_id
'req_example'
Show the optional blocking PyQt6 activation dialog on the GUI thread.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
LicenseClient
|
Persistent configured LicenseClient; use Sandbox for development. |
required |
email_required
|
bool
|
Require a nonempty email field in the dialog. Actual email/key matching is enforced by the server's product policy. |
False
|
parent
|
Any
|
Optional Qt parent widget; no PyQt import is needed until use. |
None
|
Returns:
| Type | Description |
|---|---|
LicenseResult
|
Verified activation result, refusal or local ACTIVATION_CANCELLED result. |
LicenseResult
|
Callers must require valid and signature_valid before protected work. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
The qt optional dependency is not installed. |
Examples:
Run the tested examples/pyqt_activation.py script in a desktop session. Network work blocks the dialog; this is not an asynchronous GUI framework.
Private modules and deprecated local/credentials/transport escape hatches are not stable extension APIs. Only an advanced trusted custom transport should use the private protocol; it must decode signed data losslessly.