Read license info from inside your app¶
From engine v163, every protected build exposes a small, supported API your own code can call to read the license state the runtime is operating under - so you can render a Plan or About screen without a network call.
The call¶
import builtins
get_info = getattr(builtins, "_pylocket_license_info", None)
info = get_info() if get_info else None
info is None only if protection has not initialized (or the build
predates engine v163). Otherwise it is a dict:
| Field | Meaning |
|---|---|
license_key |
The key the runtime activated with, or None if none was found locally |
expires_at |
ISO 8601 UTC expiry, or None for a perpetual license |
trial |
True while the license is a free trial issued as one: trial download links, license_type: "trial" on the API, trial redemption batches, and licenses issued on the free tier. Shopify partner trials read False (see below) |
app_id |
Your PyLocket app id |
Semantics worth knowing¶
- The key comes from the same discovery chain activation itself uses
(environment variable, the sibling
license-key.txt, then the per-user license file), so what you display always matches what the runtime honors. - The values are read fresh on every call, so a license extension or a trial conversion is reflected at the next call after the app re-checks with the server.
- Perpetual licenses report
expires_at: null- there is nothing to count down. - Shopify partner trials are not trial-flagged on the license, so
trialreadsFalsefor them. A trial from the partner/trialendpoint shows its 14-dayexpires_atonce its window has opened; a subscription trial (the webhook'strial: true) has no expiry of its own and reads like a perpetual license. For the store's trial state, ask your backend: the partner entitlement read returnstrial. - The function never raises and never returns anything secret: no key material, no tokens, no device identifiers.
- It exists only after protection initialized successfully. If your app is running, it exists.
When to use it vs a server call¶
Use this local read for display purposes - a Plan screen, an About box, a support snippet. It reflects the state on this machine. For an authoritative entitlement decision (for example, gating a server-side feature), ask your own backend, which can consult PyLocket's APIs.