# Cryptlex Documentation
A structured index of the same pages is available at [llms.txt](https://cryptlex.com/docs/llms.txt).
---
# Introduction
Section: Getting Started
URL: https://cryptlex.com/docs
Summary: Cryptlex is a software licensing platform that lets you implement any licensing model, control features and usage per license, manage customers, distribute releases, and automate order fulfillment.
Last updated: 2026-08-20
Cryptlex is a software licensing platform for desktop, server, and embedded applications. It handles the entire licensing lifecycle for you: you create and manage licenses through the [admin portal](https://app.cryptlex.com) or the [Web API](https://cryptlex.com/reference/web-api), and your app validates them using [LexActivator](https://cryptlex.com/docs/sdks-and-apis/lexactivator), the client library you embed. Each license is identified by a license key that you deliver to your customer. Beyond issuing licenses, Cryptlex manages your customers and their entitlements, hosts your releases and software updates, and automates order fulfillment, so you never have to build licensing infrastructure yourself.
Cryptlex supports every common licensing model. A license can be node-locked (locked to the machine where it is activated, which prevents casual sharing of license keys) or floating (a shared pool of seats), can additionally be tied to a named user, and it can be perpetual, subscription-based, or usage-based. You can also offer keyless timed trials before purchase. Licenses can be activated online, or without any internet connection at all in offline and air-gapped environments.
Licensing models combine, so a single license can be subscription and node-locked, or usage-based and hosted floating. Pick the combination your business needs instead of one model. See [Choosing a Licensing Model](https://cryptlex.com/docs/licensing-models/choosing-a-licensing-model).
## What can you do with Cryptlex?
* **Implement any licensing model**: subscriptions, usage-based (metered) licensing, node-locked, hosted and on-premise floating licenses, named user licenses, timed trials, and perpetual licenses. See [Choosing a Licensing Model](https://cryptlex.com/docs/licensing-models/choosing-a-licensing-model).
* **Control features per license**: decide exactly which features of your app each customer gets, turning individual features on or off or configuring their limits per license, using [feature entitlements](https://cryptlex.com/docs/features-and-entitlements/overview), and package them into tiers like Basic, Pro, and Enterprise.
* **Meter usage**: track and enforce usage limits per license, such as API calls, exports, credits, or tokens, using [meter attributes](https://cryptlex.com/docs/license-management/meter-attributes).
* **Manage your customers**: authenticate [users](https://cryptlex.com/docs/customers/users), group them into [organizations](https://cryptlex.com/docs/customers/organizations), work with [resellers](https://cryptlex.com/docs/customers/resellers), and offer self-service through the [customer portal](https://cryptlex.com/docs/customers/customer-portal).
* **Distribute releases and software updates**: host your app binaries and deliver [software updates](https://cryptlex.com/docs/releases/overview) securely to licensed users.
* **Automate order fulfillment**: generate and deliver licenses automatically on purchase using [webhooks](https://cryptlex.com/docs/integrations-and-automation/webhooks) and ready-made integrations with popular payment platforms like [Stripe](https://cryptlex.com/docs/integrations-and-automation/stripe), [FastSpring](https://cryptlex.com/docs/integrations-and-automation/fastspring), and more.
## How the pieces fit together
Cryptlex has four parts, each facing a different audience. Your team manages licensing in the admin portal, your server automates it through the Web API, your app validates licenses with a client library, and your customers and resellers serve themselves in their own portals:
### Web API
The [REST API](https://cryptlex.com/reference/web-api) through which everything in Cryptlex works. Use it to create and manage licenses and users, automate order fulfillment, and even activate licenses directly from your app without a client library.
### LexActivator
The client library you embed in your app to validate licenses. It works with every licensing model, including node-locked, hosted floating (floating licenses that need an active internet connection), timed trials, named user, and subscriptions. It handles the hard parts for you, including HTTPS communication, AES encryption, RSA signature verification, machine fingerprinting, and licensing inside virtual machines and containers, across all major platforms and languages.
### LexFloatServer & LexFloatClient
An on-premise floating license server, and the client library your app uses to lease floating licenses from it. This is recommended for mission-critical or air-gapped environments that need floating licenses without depending on a connection to Cryptlex's servers over the internet.
### Portals
The [admin portal](https://app.cryptlex.com) where your team manages products, licenses, and customers; the [customer portal](https://cryptlex.com/docs/customers/customer-portal) where your customers manage their own licenses and downloads; and the [reseller portal](https://cryptlex.com/docs/customers/resellers) where your resellers manage the customers and licenses you allow them to.
## Next steps
* Walk through the full licensing flow in [Core Concepts](https://cryptlex.com/docs/getting-started/core-concepts).
* Pick the right model for your business in [Choosing a Licensing Model](https://cryptlex.com/docs/licensing-models/choosing-a-licensing-model).
* Add licensing to your app in minutes with the [Quick Start](https://cryptlex.com/docs/getting-started/quick-start).
---
# Core Concepts
Section: Getting Started
URL: https://cryptlex.com/docs/getting-started/core-concepts
Summary: The core concepts behind licensing in Cryptlex, including products, license templates, licenses, activations, feature entitlements, meter attributes, and releases.
Last updated: 2026-08-06
Everything in Cryptlex builds on a small set of concepts. This page explains how licensing works end to end, and then defines each concept you will encounter throughout the documentation.
## How licensing works
1. **You create a product** in Cryptlex representing your application, and attach a **license template** that defines the default licensing rules (type, allowed activations, subscription interval, and so on).
2. **When a customer buys**, you create a **license** under the product, manually in the admin portal or automatically through your [order automation](https://cryptlex.com/docs/integrations-and-automation/custom-integration). This generates the license key you deliver to the customer.
3. **The customer activates** the license key in your app. Your app validates the license with the Cryptlex servers using [LexActivator](https://cryptlex.com/docs/sdks-and-apis/lexactivator) or the [Web API](https://cryptlex.com/docs/sdks-and-apis/licensing-via-web-api), and an **activation** is recorded along with the machine's fingerprint, consuming one of the license's allowed seats.
4. **On every run**, your app verifies the license locally and periodically syncs with the Cryptlex servers, picking up server-side changes such as renewals, suspension, or revocation.
5. **Optionally**, you offer [trials](https://cryptlex.com/docs/licensing-models/timed-trials) before purchase, distribute updates through [releases](https://cryptlex.com/docs/releases/overview), and give customers self-service through the [customer portal](https://cryptlex.com/docs/customers/customer-portal).
## Product
A product represents the application you want to license.
Create a single product per application, even if you sell it in multiple editions like Lite, Pro, or Enterprise; model editions with [Entitlement Sets](https://cryptlex.com/docs/features-and-entitlements/features-and-entitlement-sets) instead. Create separate products only for separate applications.
## License template
A license template is a blueprint for the licenses you create. It defines the default license properties (type, duration, allowed activations, and so on), and is the main tool for implementing your [licensing model](https://cryptlex.com/docs/licensing-models/choosing-a-licensing-model).
A single license template can be shared across products, and each product must have a default license template linked. To learn more, refer to [License Templates](https://cryptlex.com/docs/license-management/license-templates).
## Trial policy
A trial policy configures trials for your product, including the trial duration and how trial activations behave.
A single trial policy can be shared across products, but a product can have only one trial policy linked to it. Attaching a trial policy is optional; if a product has no trial policy, trials are disabled for it.
## User
A user represents a customer you license your product to. It can be as simple as a contact linked to a license, storing the customer's name and email, or the actual licensee, as in [named user licenses](https://cryptlex.com/docs/licensing-models/named-user-licenses/overview) where the license is tied to the user's identity.
Beyond that, Cryptlex provides identity management for your customers, so users can log in with an email and password or [single sign-on](https://cryptlex.com/docs/sso/overview) and manage their licenses in the [customer portal](https://cryptlex.com/docs/customers/customer-portal). To learn more, refer to [Users](https://cryptlex.com/docs/customers/users).
## Organization
An organization groups users who belong to the same company. An organization admin can manage the organization's users, form user groups, and allocate its licenses internally, without your involvement. To learn more, refer to [Organizations](https://cryptlex.com/docs/customers/organizations).
## License
A license grants a customer the right to use your product and is identified by its license key. Licenses are grouped under products and inherit all the properties of the license template attached to the product.
You can override any inherited property on an individual license if needed.
A license inherits template values only at the moment it is created. Editing a [license template](https://cryptlex.com/docs/license-management/license-templates) later does not affect licenses already created from it, so update those individually.
## Activation
An activation is created when your customer activates a license key in your app on their machine. It consumes one of the license's allowed seats.
By default, activations are node-locked, which means the machine's fingerprint is stored with the activation and the license key only works on that machine.
Deleting an activation frees the seat it consumed, so the license can then be activated on another machine. Deleting a license deletes all of its activations along with it.
## Trial activation
A trial activation is created when your customer starts a trial in your app on their machine, without a license key.
Like license activations, trial activations are node-locked by default, which prevents customers from resetting the trial by reinstalling your app.
## Feature entitlement
A feature entitlement defines a feature of your product and the value a license gets for it, letting you enable, disable, or configure features per customer. Entitlement Sets group feature entitlements into reusable tiers like Basic, Pro, and Enterprise.
To learn more, refer to [Features and Entitlements](https://cryptlex.com/docs/features-and-entitlements/overview).
## Meter attribute
A meter attribute tracks a usage count on a license, such as API calls, exports, or credits, letting you enforce usage limits and implement usage-based licensing.
To learn more, refer to [Meter Attributes](https://cryptlex.com/docs/license-management/meter-attributes).
## Maintenance policy
A maintenance policy defines how long a license is entitled to receive product updates, letting you sell time-bound maintenance separately from the license itself. It controls which release versions a license can use.
To learn more, refer to [Maintenance Policies](https://cryptlex.com/docs/licensing-models/software-maintenance-and-support).
## Release
A release represents a version of your app that you distribute through Cryptlex. Cryptlex hosts your release files, secures downloads behind license keys, and powers software updates.
To learn more, refer to [Releases](https://cryptlex.com/docs/releases/overview).
## Next steps
Now that you know how Cryptlex works, pick the licensing model that fits your business in [Choosing a Licensing Model](https://cryptlex.com/docs/licensing-models/choosing-a-licensing-model), or jump straight to the [Quick Start](https://cryptlex.com/docs/getting-started/quick-start).
---
# Quick Start
Section: Getting Started
URL: https://cryptlex.com/docs/getting-started/quick-start
Summary: Add licensing to your app in three steps by creating a product, validating licenses with LexActivator, and automating license generation with the Web API.
Last updated: 2026-07-20
The complete process of adding licensing to your app has three steps:
1. **Add a product in Cryptlex**. Log in to the [admin portal](https://app.cryptlex.com), go to the `Products` page, and add your first product along with its default [license template](https://cryptlex.com/docs/license-management/license-templates). Then go to the `Licenses` page and create your first license.
2. **Add LexActivator to your app**. [LexActivator](https://cryptlex.com/docs/sdks-and-apis/lexactivator) is the client library you embed in your app to validate licenses. It is available for all major platforms, including Windows, macOS, Linux, Android, and iOS, with bindings for most programming languages.
3. **Automate your order process**. Generate licenses automatically when an order is processed by your payment provider, using a pre-built integration like [Stripe](https://cryptlex.com/docs/integrations-and-automation/stripe), or with any payment processor using the [Web API](https://cryptlex.com/reference/web-api). To learn more, refer to [Custom Integration](https://cryptlex.com/docs/integrations-and-automation/custom-integration).
You can do all of this in a [sandbox environment](https://cryptlex.com/docs/sdks-and-apis/sandbox-environments) first and keep your production data clean.
Before you ship to real customers, walk through the [Launch Checklist](https://cryptlex.com/docs/getting-started/launch-checklist).
---
# Launch Checklist
Section: Getting Started
URL: https://cryptlex.com/docs/getting-started/launch-checklist
Summary: A checklist to walk through before shipping your app with Cryptlex, covering your licensing model, activation testing, credential security, and order automation.
Last updated: 2026-08-05
Come back to this checklist when your integration is working and you are preparing to ship to real customers. Each item links to the relevant guide.
## Licensing setup
* **Confirm your licensing model.** Make sure the model you implemented matches how you sell. Revisit [Choosing a Licensing Model](https://cryptlex.com/docs/licensing-models/choosing-a-licensing-model) if in doubt.
* **Review your license templates.** Licenses inherit their configuration from [license templates](https://cryptlex.com/docs/license-management/license-templates), so verify the license type, subscription interval, activation and deactivation limits, and lease duration (for floating licenses) before creating customer licenses.
* **Configure trials deliberately.** If you offer [timed trials](https://cryptlex.com/docs/licensing-models/timed-trials), attach a trial policy to your product and test the trial flow.
## Test your integration
* **Switch from sandbox to production.** If you built your integration against a [sandbox environment](https://cryptlex.com/docs/sdks-and-apis/sandbox-environments), make sure the app you ship uses the `Product.dat` and product ID from your production product, and that your server-side automation uses production access tokens.
* **Test the full license lifecycle in your app**: activation, periodic server sync, deactivation, and re-activation on a different machine.
* **Test failure paths, not just the happy path**: expired licenses, suspended licenses, exceeded activation limits, and no network connectivity.
* **Support offline customers.** If some of your customers run in air-gapped environments, test [offline activations](https://cryptlex.com/docs/licensing-models/offline-licenses).
* **Handle restrictive networks.** Customers behind corporate proxies or firewalls need the Cryptlex endpoints reachable. See [Proxies and Firewall](https://cryptlex.com/docs/sdks-and-apis/proxies-and-firewall).
## Secure your account and credentials
* **Never embed admin credentials in your app.** Your app should only ever contain the product data (`Product.dat`) and product ID used by [LexActivator](https://cryptlex.com/docs/sdks-and-apis/lexactivator), never your account credentials or admin access tokens.
* **Scope your access tokens.** Use least-privilege [personal access tokens](https://cryptlex.com/docs/integrations-and-automation/personal-access-tokens) for server-side automation, and rotate them if exposed.
A [personal access token](https://cryptlex.com/docs/integrations-and-automation/personal-access-tokens) belongs only in a trusted backend service you control. Never ship one in a desktop, mobile, or browser application, not even in compiled code or an environment variable, since anything on a customer's machine can be inspected and the token could then be used to read or modify your licenses. Your app needs only `Product.dat` and your product ID.
## Automate your operations
* **Generate licenses on purchase** using a pre-built payment integration like [Stripe](https://cryptlex.com/docs/integrations-and-automation/stripe), your own [custom integration](https://cryptlex.com/docs/integrations-and-automation/custom-integration) with [webhooks](https://cryptlex.com/docs/integrations-and-automation/webhooks), or a no-code [Zapier](https://cryptlex.com/docs/integrations-and-automation/zapier) workflow.
* **Set up automated emails** so customers receive their license keys and expiry reminders without manual work. See [Automated Emails](https://cryptlex.com/docs/integrations-and-automation/automated-emails).
* **Offer self-service** with the [customer portal](https://cryptlex.com/docs/customers/customer-portal) so customers can view licenses and manage activations themselves.
## Distribution and updates
* **Plan how you ship updates.** Use [releases](https://cryptlex.com/docs/releases/overview) to host your binaries and deliver updates to licensed users.
## Need help?
If you are unsure about any of the above, contact us through the [contact page](https://cryptlex.com/contact).
---
# Choosing a Licensing Model
Section: Licensing Models
URL: https://cryptlex.com/docs/licensing-models/choosing-a-licensing-model
Summary: Compare the licensing models Cryptlex supports (perpetual, subscription, usage-based, node-locked, floating, and named user licenses) and decide which one fits your business.
Last updated: 2026-08-06
Cryptlex supports every common software licensing model. A licensing model is really two independent choices: how your customers pay (perpetual, subscription, or usage-based) and how the license is enforced (node-locked or floating, optionally tied to a named user). You can combine any option from one dimension with any option from the other, for example a subscription license that floats, or a perpetual license locked to one machine. This guide explains each option and helps you decide, then points you to the implementation guide for each.
## How customers pay
### Perpetual
A perpetual license has no subscription interval or expiration date set. A customer buys the license once and can use your product for life without paying again.
Perpetual does not have to mean free updates forever. Attach a [maintenance policy](https://cryptlex.com/docs/licensing-models/software-maintenance-and-support) to cap how long the application receives new updates, so you can sell updates and support separately.
### Subscriptions
Subscription licenses expire after a set period. Your customers usually pay a monthly or yearly subscription fee, and when they renew, the license is renewed as well. To learn more, refer to [License Subscriptions](https://cryptlex.com/docs/licensing-models/subscription-licensing).
### Usage-based
Sometimes you want your customers to pay for what they actually use, regardless of how long they possess your product. Usage can be defined as the amount of time your app is used, the number of times it is run, or the number of specific operations performed, depending on your business requirements. To learn more, refer to [Usage-Based Licensing](https://cryptlex.com/docs/licensing-models/usage-based-licensing).
Usage-based pricing does not have to replace perpetual or subscription pricing. [Meter attributes](https://cryptlex.com/docs/license-management/meter-attributes) are properties on a license, so you can meter a perpetual license or put usage ceilings on a subscription.
## How licenses are enforced
### Node-locked licenses
A node-locked license is locked to the machine on which it is activated. If the license allows a single activation (seat), the license key cannot be used on any other machine, unless you allow deactivation, which frees the seat so the license can be activated on a different machine.
If the license allows multiple activations (multi-seat), then after all the activations are used, the license key cannot be used on other machines. To learn more, refer to [Node-Locked Licenses](https://cryptlex.com/docs/licensing-models/node-locked-licenses).
### Floating licenses
A floating license is bound to a machine for a specific amount of time, called the lease. While your app runs, it automatically renews the lease in the background at the server sync interval, so the seat stays held. When the app stops renewing and the lease duration elapses, the seat is freed automatically, so that another machine can use the license.
So if your floating license allows 100 activations (seats), then at any instant no more than 100 machines can use your application.
Cryptlex supports [hosted floating licenses](https://cryptlex.com/docs/licensing-models/floating-licenses/hosted-floating-licenses), where the Cryptlex servers act as the license server, and [on-premise floating licenses](https://cryptlex.com/docs/licensing-models/floating-licenses/on-premise-floating-licenses), where LexFloatServer runs inside your customer's network. Choose between them on connectivity: a hosted floating license needs a working internet connection to the Cryptlex servers to lease and renew a seat, while an on-premise floating license keeps working in offline and air-gapped environments.
### Named user licenses
A named user license (also known as identity-based licensing or user-locked license) is tied to a specific user, who logs in to retrieve their license. It is not a third kind of binding: a named user license is itself node-locked or floating, and additionally tied to the user's identity. To learn more, refer to [Named User Licenses](https://cryptlex.com/docs/licensing-models/named-user-licenses/overview).
## Feature-based licensing
On top of either dimension, you can control which capabilities of your product each license unlocks, so you can sell tiers like Standard, Pro, and Enterprise from a single build of your app. It is not a separate license type; you attach feature entitlements to any license. To learn more, refer to [Feature-Based Licensing](https://cryptlex.com/docs/licensing-models/feature-based-licensing).
## Trials
You can offer timed trials of your product so customers can evaluate it before buying. To learn more, refer to [Timed Trials](https://cryptlex.com/docs/licensing-models/timed-trials).
## Which licensing model should I choose?
Most of the time you will use node-locked licenses, either perpetual or subscription based.
When licensing your product to a university or a large company that needs many license seats, you will usually opt for floating licenses, as that is more economical for your customers.
You can also add restrictions like usage counts, or implement a completely custom licensing model using [metadata](https://cryptlex.com/docs/license-management/metadata) fields on your licenses. For how each model maps to license template properties, refer to [Implementing License Models](https://cryptlex.com/docs/licensing-models/implementing-license-models).
## Need help
If you need help implementing any of these licensing models, we'll be glad to assist. Contact us through the [contact page](https://cryptlex.com/contact).
---
# Implementing License Models
Section: Licensing Models
URL: https://cryptlex.com/docs/licensing-models/implementing-license-models
Summary: The license template settings that implement each licensing model, from perpetual and subscription to floating and named user licenses.
Last updated: 2026-08-06
Once you have [chosen a licensing model](https://cryptlex.com/docs/licensing-models/choosing-a-licensing-model), you can implement it using license templates, or by overriding the properties of the license template when creating a license. The latter allows you to create a variant without creating a new template.
## License template configuration for different licensing models
The sections below list the properties that implement each model. These properties are combinable, not mutually exclusive: a single license can be, for example, node-locked, subscription-based, and named-user all at once. Set the properties for each dimension your model needs.
### Perpetual
A perpetual (lifetime) license does not have a subscription interval or an expiration date set.
Property
Value
**`subscriptionInterval`**
`null`
Perpetual controls payment, not access to updates. To limit which releases the application receives, attach a [maintenance policy](https://cryptlex.com/docs/licensing-models/software-maintenance-and-support), configured separately from the license template.
### Subscription
A subscription expires after a specific duration of time. When a license expires, LexActivator returns the `LA_EXPIRED` status code.
Property
Value
**`subscriptionInterval`**
`P1M`
### Node-locked
A node-locked license is locked to the machines on which it is activated, up to its `allowedActivations` limit. Set the license type to `node-locked`.
Property
Value
**`type`**
`node-locked`
### OS user-locked
An OS user-locked license is a node-locked license that additionally prevents different users (OS users) on the same machine from re-using the same license.
The `userLocked` property refers to operating system user accounts, so each OS user on a machine consumes a separate activation. It is unrelated to [named user licensing](https://cryptlex.com/docs/licensing-models/named-user-licenses/overview), where the licensee logs in with Cryptlex credentials.
Property
Value
**`type`**
`node-locked`
**`userLocked`**
`true`
### Hosted-floating
The hosted-floating type implements a floating licensing model without requiring your customer to install a license server, with Cryptlex's servers acting as the license server.
Property
Value
**`type`**
`hosted-floating`
**`leaseDuration`**
`>0`, or `0`/`-1` for an unlimited lease
**`leasingStrategy`**
`per-machine`
Do not call `ActivateLicense()` unconditionally on startup. See the [recommended activation flow](https://cryptlex.com/docs/licensing-models/floating-licenses/hosted-floating-licenses#adding-floating-licensing-to-your-app) for hosted floating licenses.
To let the end user set the lease duration, enable the [allow client lease duration](https://cryptlex.com/docs/license-management/license-templates#allow-client-lease-duration) property and call `SetActivationLeaseDuration()` in your app before activating.
An activation is held by a lease, and the Cryptlex servers free it once a lease is not renewed within the configured `leaseDuration`. A crashed app therefore holds its activation until the lease elapses, which is a [zombie license](https://cryptlex.com/docs/licensing-models/floating-licenses/overview#zombie-licenses), so release the activation when your app exits by invoking `DeactivateLicense()`.
### Hosted-floating (instance-locked)
Instead of locking a floating license to a machine, you can lock it to the application instance (process) by setting the leasing strategy to `per-instance`. Each running instance consumes a seat, regardless of whether instances share the same device fingerprint. This is what makes floating licenses work inside cloned VMs, Docker containers, and Kubernetes workloads (see [Containers and Virtual Machines](https://cryptlex.com/docs/licensing-models/containers-and-virtual-machines)), and it lets you charge your customer per running instance.
An activation registered by an instance can only be deactivated from within that same instance.
Property
Value
**`type`**
`hosted-floating`
**`leaseDuration`**
`>0`, or `0`/`-1` for an unlimited lease
**`leasingStrategy`**
`per-instance`
### On-premise-floating
The on-premise-floating type implements a floating licensing model in environments which may or may not be connected to the internet. Your customer installs [LexFloatServer](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/overview) in their network. The `allowedFloatingClients` property sets how many application instances the server can serve concurrently.
For on-premise floating licenses, the activations limit defined in your plan applies only to the number of LexFloatServer instances that can be activated, while any number of LexFloatClient instances served by each activated LexFloatServer is not counted toward the on-premise floating license limit.
Property
Value
**`type`**
`on-premise-floating`
**`leaseDuration`**
`0`, `>0`
**`allowedFloatingClients`**
`>0`
### Single-seat
The number of machines a license key can be used on is determined by the `allowedActivations` property.
Property
Value
**`allowedActivations`**
`1`
**`type`**
`node-locked`, `hosted-floating`
### Multi-seat
A single key can be used on multiple machines if the value of the `allowedActivations` property is greater than one.
Property
Value
**`allowedActivations`**
`>1`
**`type`**
`node-locked`, `hosted-floating`
### Unlimited-seat
You can allow an unlimited number of seats for a license (site license), and restrict the site using an IP address or location.
Property
Value
**`allowedActivations`**
`0`, `-1`
**`type`**
`node-locked`, `hosted-floating`
**`allowedIpAddresses`**
`[125.67.123.43]`
### Named-user
A named-user license has no dedicated license type. You assign the license to a specific individual, typically identified by an email address, by linking the user to it at creation time, on top of any node-locked or floating configuration. The user logs in with their credentials to retrieve their license key, after which activation proceeds like any other license. To learn more, refer to [Named User Licenses](https://cryptlex.com/docs/licensing-models/named-user-licenses/overview).
Linking a user to a license does not by itself make it a named user license, and does not change how the license is enforced. Your app must authenticate the user through the [named user workflow](https://cryptlex.com/docs/licensing-models/named-user-licenses/overview), otherwise the linked user is just stored customer data.
### Usage-based
A usage-based (metered) license has no dedicated license type. Instead, you add meter attributes to any license type defined above to track and enforce usage counts. To make specific meter attributes mandatory for every license, add them to the `requiredMeterAttributes` property of the license template. To learn more, refer to [Usage-Based Licensing](https://cryptlex.com/docs/licensing-models/usage-based-licensing).
---
# Subscription Licensing
Section: Licensing Models
URL: https://cryptlex.com/docs/licensing-models/subscription-licensing
Summary: Cryptlex license subscriptions enable time-based licensing with flexible intervals, expiration dates, and renewals.
Last updated: 2026-08-06
In Cryptlex, a subscription is a time-based licensing model where a license is valid for a specific duration, such as months or years. It suits recurring billing and time-limited access, and combines with any enforcement type (node-locked, floating, or named user). A subscription is configured by setting a subscription interval or an exact expiration date.
Use a subscription when you want recurring revenue or to bundle ongoing updates and support. For a one-time purchase with no expiry, use a perpetual license instead.
## Adding a subscription to a license
To configure a subscription in a license, you can define:
- A **subscription interval** and **start trigger**, or
- A fixed **expiration date**
Set one or the other, not both. These settings define the start of the license term and how its expiry is determined.
### Using a subscription interval and start trigger
To define a recurring subscription, use the `subscriptionInterval` property to specify the duration and the `subscriptionStartTrigger` to determine when that duration begins.
The subscription interval accepts ISO 8601 durations (`P1Y`, `P3M10D`, `P30D`), which automatically account for varying month and year lengths. The start trigger controls when the period begins:
Start trigger
Period begins
Use when
**License Creation**
When the license is created
You want it aligned with the purchase date
**License Activation**
When the license is first activated
It should begin with first product use
### Using an expiration date
Alternatively, you can set a fixed expiration date by setting the `expiresAt` property of the license to define exactly when the license should expire.
## Renewing a subscription
When a subscription is renewed, Cryptlex adds the current `subscriptionInterval` to the expiration date, renewing the license for another cycle. The license can be renewed manually from the admin portal or through the Web API.
- Admin portal: Go to the [Licenses](https://app.cryptlex.com/license-management/licenses) page, click the Actions menu (three dots) next to the license, and select **`Renew License`**.
- Web API: Send a `POST` request to the [Renew License](https://cryptlex.com/reference/web-api/post-licenses-id-renew) endpoint.
A renewal extends the existing license, so your customer does not activate again and their license key does not change. An expired subscription can still be renewed, so there is no need to recreate it. Their app picks up the new expiration date at its next [server sync](https://cryptlex.com/docs/license-management/license-templates#server-sync-interval), and can rely on cached license state only for as long as the [server sync grace period](https://cryptlex.com/docs/license-management/license-templates#server-sync-grace-period) allows, after which LexActivator returns `LA_GRACE_PERIOD_OVER`.
## Updating the expiration date
The `expiresAt` property of the license can be updated manually to extend, shorten, or correct the license's expiration date, either from the admin portal or through the Web API.
- Admin portal: Go to the [Licenses](https://app.cryptlex.com/license-management/licenses) page, click the Actions menu (three dots) next to the license, and select **`Update Expiration Date`**.
- Web API: Send a `PATCH` request to the [Update License Expiration](https://cryptlex.com/reference/web-api/patch-licenses-id-expires-at) endpoint.
Updating `expiresAt` changes only the current expiration date. The license keeps its `subscriptionInterval`, so a one-off adjustment does not change the length of future cycles.
## Subscription logs
Subscription logs track the history of subscription-related events for each license, which helps you audit and troubleshoot subscription changes over time. Captured events include license expiration date updates (`license.expiresAt.updated`), license renewals (`license.renewed`), and modifications to subscription details (`license.subscription.updated`).
You can view these logs on the `Licenses -> Subscription Logs` page in the admin portal.
## Setting an effective date
The `effectiveDate` license property defines the earliest date on which the license can be activated. Any attempt to activate the license before this date is rejected, even if the license key has already been delivered to the customer. This applies to any license, independent of its subscription settings.
The effective date does not extend the subscription; it only blocks activation until the date arrives. With the **License Creation** subscription start trigger, the term is already running while the customer is locked out, so use **License Activation** subscription start trigger to give them the full term from first use.
You can find this property under the `Advanced` tab while creating a license in the admin portal.
---
# Node-Locked Licenses
Section: Licensing Models
URL: https://cryptlex.com/docs/licensing-models/node-locked-licenses
Summary: Cryptlex implements node-locked licensing through LexActivator, which locks a license to a machine using a device fingerprint and supports online and offline activation.
Last updated: 2026-08-06
A node-locked license is bound to the machine on which it is activated. When your app activates the license, LexActivator generates a unique device fingerprint and sends it with the activation request. Cryptlex stores that fingerprint and checks it on every further activation attempt, so the same license key cannot be used on another machine.
Whether a hardware change breaks the match depends on the license's [fingerprint matching strategy](https://cryptlex.com/docs/license-management/license-templates#fingerprint-matching-strategy). **Exact** treats any minor change as a different machine, while **Fuzzy**, the recommended strategy, tolerates minor changes. **Loose** applies a lower threshold for machines that report unstable fingerprints.
This is the most common licensing model, and the right default when each of your customers runs your app on a known set of machines.
You implement it with [LexActivator](https://cryptlex.com/docs/sdks-and-apis/lexactivator) embedded in your app, which handles device fingerprinting, encrypted local license storage, virtual machine detection, time tampering detection, and periodic server sync for you. It also determines how the license is activated, online or offline, and how an activation is scoped across the machine's OS users.
Your app does not contact Cryptlex servers on every launch. `IsLicenseGenuine()` validates the stored activation locally by checking its cryptographic signature, which works offline and adds no startup latency, and the server sync runs in a background thread. See [verify locally, sync in the background](https://cryptlex.com/docs/sdks-and-apis/best-practices#verify-locally-sync-in-the-background).
## Online and offline activation
A node-locked license can be activated online or offline. When the machine has internet access, your app can activate directly against the Cryptlex servers. When it has no internet access, you activate offline by exchanging request and response files through the admin or customer portal. See [Offline Activations](https://cryptlex.com/docs/licensing-models/offline-licenses) for the offline process.
An offline activation is validated and enforced exactly like an online one. The difference is that a machine with no connection never syncs, so a renewal, suspension, or revocation only reaches it once it gets internet access or consumes a fresh offline response. Plan for that before relying on revoking access remotely.
## Setting the activation scope
LexActivator's `SetProductId()` function takes a permission flag that determines where the activation is stored on the machine and which OS users can see it. Two flags apply to node-locked licensing:
- **`LA_USER`** (the default) stores the activation under the OS user who activated the license, so it is visible only to that user, and each OS user who runs the app activates separately. They all share the same seat. Enable [OS user-locked](https://cryptlex.com/docs/licensing-models/implementing-license-models#os-user-locked) to have each OS user consume a separate seat.
- **`LA_ALL_USERS`** stores the activation system-wide and shares it across all OS users on the machine.
The permission flag and the `userLocked` license property are independent and easy to confuse. The flag decides where the activation is stored and which OS users can see it, set in your app's code. `userLocked` decides whether each OS user consumes a separate seat, set on the license or its template.
`LA_ALL_USERS` is supported on Windows and macOS. On Linux, achieve the same result by pointing LexActivator at a system-wide directory with `SetDataDirectory()` and passing the `LA_ALL_USERS` flag.
LexActivator offers additional flags for services and in-memory storage. See [Best Practices](https://cryptlex.com/docs/sdks-and-apis/best-practices#choose-the-right-permission-flag) for the full list.
## Next steps
- For the SDK setup, activation calls, and language-specific samples, refer to [Using LexActivator](https://cryptlex.com/docs/sdks-and-apis/lexactivator).
---
# Overview
Section: Licensing Models > Floating Licenses
URL: https://cryptlex.com/docs/licensing-models/floating-licenses/overview
Summary: Floating licenses share a limited pool of seats among many users by leasing them for a set time, served either by Cryptlex (hosted) or by a server in your customer's network (on-premise).
Last updated: 2026-08-05
Floating licenses (also known as concurrent or network licenses) allow a limited number of licenses for your app to be shared among a larger number of users over time. When authorized users wish to run the app, they request a license from a license server.
Suppose your customer has 30 employees who will use your app, but fewer than 20 of them use it concurrently. Instead of purchasing 30 individual licenses, your customer only purchases the number of floating licenses required to support the concurrent users.
Floating licenses are usually more economical than purchasing individual node-locked licenses.
## How floating licenses work
When your app starts, it requests a floating license from the license server. The license server checks the number of available seats, and if it finds a free one, it leases the license to your app for a specified amount of time. If all seats are leased, the next user must wait until another user's app frees its seat or its lease expires.
Before the lease expires, your app automatically sends a refresh request to the license server to extend it. When your user is done using the app, the app should free the license, making it available for other users.
For hosted floating licenses the refresh happens during the server sync, so keep the [server sync interval](https://cryptlex.com/docs/license-management/license-templates#server-sync-interval) at least 30 seconds shorter than the [lease duration](https://cryptlex.com/docs/license-management/license-templates#lease-duration). Otherwise the lease lapses before the refresh arrives and your user loses the seat while still working.
## Hosted vs on-premise floating license server
The two types differ in where the license server runs and the client library your app uses to lease seats from it.
Option
License server
Client library
Best for
[Hosted floating](https://cryptlex.com/docs/licensing-models/floating-licenses/hosted-floating-licenses)
Cryptlex servers
LexActivator
Apps with internet access
[On-premise floating](https://cryptlex.com/docs/licensing-models/floating-licenses/on-premise-floating-licenses)
LexFloatServer, in your customer's network
LexFloatClient
Air-gapped or offline networks
## Zombie licenses
If your app stops without freeing its seat, the seat stays leased and unavailable to others until the lease expires. This is called a zombie license. It resolves on its own once the lease runs out, because the server frees any seat whose lease is not refreshed. To prevent it, always free the seat when your app exits.
## Borrowing for offline use
A user can borrow a floating license to keep using your app while disconnected. How you enable borrowing differs by deployment, so see the [hosted](https://cryptlex.com/docs/licensing-models/floating-licenses/hosted-floating-licenses#borrowing-for-offline-use) and [on-premise](https://cryptlex.com/docs/sdks-and-apis/lexfloatclient#borrowing-a-license-for-offline-use) pages for the specifics.
---
# Hosted Floating Licenses
Section: Licensing Models > Floating Licenses
URL: https://cryptlex.com/docs/licensing-models/floating-licenses/hosted-floating-licenses
Summary: Implement hosted floating licenses with LexActivator, where Cryptlex servers act as the license server, so you need no license server of your own.
Last updated: 2026-08-05
With hosted floating licenses, Cryptlex's servers act as the license server, so your app leases seats directly from Cryptlex and you only need [LexActivator](https://cryptlex.com/docs/sdks-and-apis/lexactivator). For how floating licensing works in general, see the [Floating Licenses overview](https://cryptlex.com/docs/licensing-models/floating-licenses/overview).
## Creating a hosted floating license
When creating the license, configure it as follows:
* Set the license type to `hosted-floating`.
* Set the lease duration to how long you want each seat leased.
* Keep the server sync interval shorter than the lease duration by at least 30 seconds, since server sync is what renews the lease.
The lease duration is a tradeoff. A long lease holds a seat for its full duration after an app crashes, so stale seats come back slowly. A short lease reclaims them sooner, but forces more frequent syncs and a higher volume of API requests.
## Adding floating licensing to your app
You implement hosted floating licenses the same way as node-locked licenses with [LexActivator](https://cryptlex.com/docs/sdks-and-apis/lexactivator), with a difference in how you activate and release seats: validate the license first, activate only when needed, and release the seat on exit so it does not become a [zombie](https://cryptlex.com/docs/licensing-models/floating-licenses/overview#zombie-licenses). For the implementation and code sample, see [hosted floating licenses](https://cryptlex.com/docs/sdks-and-apis/lexactivator#hosted-floating-licenses).
## Borrowing for offline use
To let a user work offline, lease the license for a longer duration by calling `SetActivationLeaseDuration()` before activating, so the app keeps working while disconnected and the seat is freed automatically when the lease expires. This requires enabling the license's [allow client lease duration](https://cryptlex.com/docs/license-management/license-templates#allow-client-lease-duration) property. For on-premise deployments, borrowing works differently, through [offline floating licenses](https://cryptlex.com/docs/sdks-and-apis/lexfloatclient#borrowing-a-license-for-offline-use).
A borrowed seat is not a free seat. It stays counted against the license for the whole lease duration even though the user is offline, so a few users borrowing for weeks at a time reduces the concurrent seats available to everyone else. Account for it when deciding how many seats to sell.
---
# On-Premise Floating Licenses
Section: Licensing Models > Floating Licenses
URL: https://cryptlex.com/docs/licensing-models/floating-licenses/on-premise-floating-licenses
Summary: Cryptlex on-premise floating licenses use LexFloatServer and LexFloatClient to lease seats inside offline or air-gapped networks, with no dependency on external connectivity.
Last updated: 2026-08-06
On-premise floating licenses are [floating licenses](https://cryptlex.com/docs/licensing-models/floating-licenses/overview) where the license server runs inside your customer's own network instead of on Cryptlex's servers. Your customer runs LexFloatServer and activates it with the license key you issue, and it governs all licensing locally. This suits restricted environments such as air-gapped or offline networks.
Client applications use the [LexFloatClient](https://cryptlex.com/docs/sdks-and-apis/lexfloatclient) library to connect to LexFloatServer over the local network and request seats, so licensing keeps working with no external internet access.
On-premise floating licensing needs no internet access, not even for LexFloatServer itself. The server can be [activated offline](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/activating-the-lexfloatserver) by exchanging request and response files, generated either in the admin portal or by your customer in the [customer portal](https://cryptlex.com/docs/customers/customer-portal).
## How your app obtains a floating license
To obtain a floating license from the LexFloatServer, your app uses the LexFloatClient library. Each time the app requests a seat through LexFloatClient, LexFloatServer checks one out and reduces the available pool. If all seats are in use, the next user waits until an active user releases a seat or a lease expires. To avoid a [zombie seat](https://cryptlex.com/docs/licensing-models/floating-licenses/overview#zombie-licenses), release the seat with `DropFloatingLicense()` when your app exits.
## Setting up on-premise floating licensing
1. [Install](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/installing-lexfloatserver), [configure](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/configuring-and-startup), and [activate](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/activating-the-lexfloatserver) LexFloatServer on your customer's network.
2. [Integrate LexFloatClient](https://cryptlex.com/docs/sdks-and-apis/lexfloatclient) into your app to lease seats from the server.
Your app must be able to reach LexFloatServer over the network. The server listens on port `8090` by default, and your app points at it with `SetHostUrl()`, for example `http://:8090`. Open that port in the firewall on the machine running LexFloatServer.
---
# Overview
Section: Licensing Models > Named User Licenses
URL: https://cryptlex.com/docs/licensing-models/named-user-licenses/overview
Summary: Named user licenses tie a license to a specific user who activates it by logging in with their credentials instead of a license key, with optional OIDC SSO through an external identity provider.
Last updated: 2026-08-06
A named user license (also known as identity-based licensing or user-locked license) ties a license to a specific user, identified by their email address. The user activates the license by logging in with their credentials, so they never enter a license key.
Named user licenses can be either node-locked or hosted floating. Regardless of the type, users must authenticate to access the licenses associated with their account.
Named user licensing is most useful for organizations, where each seat is tied to a specific member who logs in with their own credentials. It also works for standalone users.
The user must be linked to the license in Cryptlex before activation. The flow retrieves that linked license after the user logs in, so the user never enters a license key.
## Activating a named user license
The user must authenticate before their licenses can be activated. The flow has three steps:
1. **Authenticating the user**: authenticate the user by calling the `AuthenticateUser(string email, string password)` LexActivator API function.
If your users log in through an identity provider instead of Cryptlex credentials, authenticate them with the `AuthenticateUserWithIdToken()` function using [OIDC SSO](https://cryptlex.com/docs/licensing-models/named-user-licenses/oidc-sso).
If the user has enabled two-factor authentication (2FA), the function fails with the `LA_E_TWO_FACTOR_AUTHENTICATION_CODE_MISSING` error. Provide the 2FA code with `SetTwoFactorAuthenticationCode()`, then call `AuthenticateUser()` again.
2. **Retrieving the user license**: after successful authentication, call `GetUserLicenses()` to retrieve the licenses linked to the user, and pass the chosen license key to `SetLicenseKey()`. If multiple licenses are linked, prompt the user to select one.
3. **Activating the license**: once the license key is set, call `ActivateLicense()`. Activation is the same as for regular licenses; refer to the guide for your [programming language](https://cryptlex.com/docs/sdks-and-apis/lexactivator).
Logging in is how your app obtains and activates the license, not something it repeats on every run. Once activated, the license behaves exactly like any other node-locked or hosted floating license, and your app verifies it locally with `IsLicenseGenuine()`.
---
# OIDC SSO
Section: Licensing Models > Named User Licenses
URL: https://cryptlex.com/docs/licensing-models/named-user-licenses/oidc-sso
Summary: Cryptlex supports OpenID Connect SSO, letting you authenticate in-app users with an external identity provider through LexActivator.
Last updated: 2026-07-14
Cryptlex supports single sign-on in your app through OpenID Connect (OIDC). This allows your end users to authenticate using trusted identity providers such as Google, Microsoft, Okta, and others. You use OIDC SSO when implementing [named user licenses](https://cryptlex.com/docs/licensing-models/named-user-licenses/overview), where users log in through your identity provider instead of Cryptlex credentials before activating their license.
OIDC SSO is available in your app through **LexActivator** 3.24.0 or later (use the latest version). It is not available in the web portals, which support [Google SSO](https://cryptlex.com/docs/sso/google-sso) and [SAML SSO](https://cryptlex.com/docs/sso/saml-sso) instead.
## Configuring single sign-on with OIDC
To enable OIDC SSO in your Cryptlex account, go to the `Settings -> Account` page in the admin portal and click the **`Configure OIDC SSO`** button.
In the configuration dialog, provide the following details from your identity provider (IdP):
* **Client ID:** The unique identifier assigned to your application by the IdP.
* **Additional Client IDs:** A comma-separated list of secondary client IDs, if applicable.
* **IdP Issuer URL:** The issuer URL of your OIDC provider.
* **Default Role:** The role assigned to newly provisioned users when no role claim is provided by the IdP.
* **Name Claim:** The claim that contains the user's name.
* **Email Claim:** The claim that contains the user's email address.
* **Role Claim:** The claim that contains the user's role.
* **Auto-Provision Users on First Login:** When enabled, the IdP must supply the name, email, and role claims configured above. These attributes are required for just-in-time (JIT) user provisioning in Cryptlex.
After completing all required fields, save the configuration to enable OIDC SSO.
## Using OIDC with LexActivator
LexActivator includes built-in support for OIDC authentication, enabling your application to validate users through your configured identity provider before proceeding with license operations.
### Authenticating the user
The authentication workflow remains the same as the process described in the [Named User Licenses](https://cryptlex.com/docs/licensing-models/named-user-licenses/overview) documentation, including user license retrieval and activation. The only difference is the use of the `AuthenticateUserWithIdToken()` function in place of the `AuthenticateUser()` function.
LexActivator does not handle the OIDC authentication flow. Your application must complete the authentication with the identity provider and pass the ID token to LexActivator for user authentication.
---
# Usage-Based Licensing
Section: Licensing Models
URL: https://cryptlex.com/docs/licensing-models/usage-based-licensing
Summary: Implement usage-based (metered) licensing in Cryptlex with meter attributes, charging customers for what they consume, such as API calls, exports, or credits.
Last updated: 2026-07-13
Usage-based licensing, also called metered or consumption-based licensing, charges customers for what they consume instead of, or in addition to, how long they hold a license or how many seats they use. Cryptlex implements it with [meter attributes](https://cryptlex.com/docs/license-management/meter-attributes), which track and enforce usage counts on each license.
## How it works
A meter attribute moves through the same lifecycle on every license:
1. **Define** the meter attribute on the license, with its **Allowed Uses** limit. Require it on every license by adding it to the license template's required meter attributes. Set Allowed Uses to `-1` to track usage without enforcing a cap.
2. **Report usage** at runtime. Each time the metered action happens in your app, increment the count, by 1 or in bulk, using the meter attribute functions in your SDK. You can also decrement or reset it to match your billing logic.
3. **Aggregate.** Each activation's uses roll up into the license's Total Uses, so every machine draws from one shared pool. Gross Uses records the lifetime total.
4. **Enforce.** When Total Uses reaches Allowed Uses, further increments fail with a limit-reached error code and the operation can be blocked, while the license itself stays genuine.
5. **Report and reset.** Metering is a real-time call to the Cryptlex server, so Total Uses stays current. For offline node-locked and hosted floating scenarios, buffer counts locally and apply them in bulk when the connection returns; on-premise floating licenses meter through LexFloatServer, which works offline. If you bill per cycle, reset Total Uses at the start of each period; Gross Uses keeps climbing.
See [Meter Attributes](https://cryptlex.com/docs/license-management/meter-attributes) for the exact SDK functions and error codes for each license type.
## Common pricing shapes
* **Credits or tokens**: sell a bundle of credits or tokens as the license's allowed uses; each operation consumes them, and the customer buys a top-up when they run out.
* **Pay per use with periodic billing**: combine meter attributes with a [license subscription](https://cryptlex.com/docs/licensing-models/subscription-licensing); read the total uses each billing cycle to invoice the customer, then reset the count. The gross uses property keeps the lifetime total across resets.
* **Fair-use caps**: keep a time-based subscription but put usage ceilings on expensive operations.
## Next steps
* Read [Meter Attributes](https://cryptlex.com/docs/license-management/meter-attributes) for the full list of properties, visibility permissions, and the LexActivator functions to use in your app.
* Compare with the other models in [Choosing a Licensing Model](https://cryptlex.com/docs/licensing-models/choosing-a-licensing-model).
---
# Feature-Based Licensing
Section: Licensing Models
URL: https://cryptlex.com/docs/licensing-models/feature-based-licensing
Summary: Implement feature-based licensing in Cryptlex with feature entitlements, selling product tiers and per-license capabilities from a single build of your app.
Last updated: 2026-08-05
Feature-based licensing controls which capabilities of your product each license unlocks, so you can sell tiers like Standard, Pro, and Enterprise, or enable individual features per customer, all from one build of your app. It is not a separate license type: you attach [feature entitlements](https://cryptlex.com/docs/features-and-entitlements/overview) to any node-locked or floating license to enable, disable, and configure features.
## How it works
1. Define your product's features in the admin portal. A feature present on a license is enabled, and each feature can carry an optional value (string, number, or boolean) for your app to interpret.
2. Package features into reusable Entitlement Sets to model tiers (Standard, Pro, Enterprise), or assign feature entitlements directly to a license for per-customer needs. You can combine both, and license-level entitlements override the Entitlement Set.
3. Your app reads the license's feature entitlements at runtime through the SDK (LexActivator or LexFloatClient) and enables, hides, or configures functionality accordingly. See [Accessing Feature Entitlements](https://cryptlex.com/docs/features-and-entitlements/accessing-feature-entitlements) for the exact functions.
4. Optionally set an expiry date on a license-level feature entitlement for time-bound access, such as feature trials or temporary unlocks.
Entitlement changes are not instant. When you enable a feature on a license, your customer's app keeps reading the entitlements it already holds until its next [server sync](https://cryptlex.com/docs/license-management/license-templates#server-sync-interval) completes.
Feature entitlements enable and configure features; they do not track consumption. To meter usage against a quota, such as API calls or exports, use [meter attributes](https://cryptlex.com/docs/license-management/meter-attributes), which implement [usage-based licensing](https://cryptlex.com/docs/licensing-models/usage-based-licensing). You can combine the two on the same license.
## Common patterns
* **Product tiers**: group features into Entitlement Sets (Standard, Pro, Enterprise) and link the right set to each license.
* **Value-based limits**: use a feature value such as `max_projects = 20` that your app enforces at runtime.
* **Beta rollouts**: add a feature like `beta_dark_mode` to selected licenses to gate functionality without separate builds.
* **Feature trials**: set an expiry date on a license-level feature entitlement for temporary access.
## Next steps
* Read [Feature Entitlements](https://cryptlex.com/docs/features-and-entitlements/overview) for the full model, assignment options, and SDK access.
* Compare with the other models in [Choosing a Licensing Model](https://cryptlex.com/docs/licensing-models/choosing-a-licensing-model).
---
# Offline Licenses
Section: Licensing Models
URL: https://cryptlex.com/docs/licensing-models/offline-licenses
Summary: Activate node-locked licenses on machines with no internet access by exchanging offline request and response files through the admin or customer portal.
Last updated: 2026-09-14
When a machine has no internet access at the time of activation, your app cannot reach the Cryptlex servers directly. Instead, you activate the license offline by exchanging files through the admin or customer portal.
## How offline activation works
1. **Your app generates a request file.** The user enters their license key, and LexActivator writes an offline activation request file that identifies the license and the machine.
2. **The request is exchanged for a response.** You (or your customer) upload the request file on the admin or customer portal from any machine that has internet access, such as a phone, laptop, or edge device. The portal validates it and returns an offline activation response file that is valid for a limited period.
3. **Your app consumes the response.** LexActivator reads the response file to activate the license on the offline machine and stores the activation on disk in encrypted form.
Once activated, your app verifies the license locally on every start, with no internet access required. For a time-bound license, LexActivator returns the `LA_EXPIRED` status when the license expires, which your application should handle based on your business requirements.
While the machine has no connection, nothing you change on the license reaches it. Renewals, suspension or revocation, entitlement changes, and updated metadata all apply only once the machine completes a server sync or consumes a fresh offline activation response. Take that into account before relying on remote changes to an offline license.
## What the offline request file contains
The request file that `GenerateOfflineActivationRequest()` writes is an encrypted blob, not human-readable. Its payload is essentially the same JSON an online activation sends to the Cryptlex servers, identifying the license and the machine:
",
"releaseVersion": "1.4.2",
"os": "windows",
"metadata": {},
...
}`} />
The response file the portal returns is an encrypted, signed token with a validity window (see [Creating the activation response](#creating-the-activation-response)). LexActivator verifies the signature and confirms the machine's current fingerprint still matches before activating, so the activation cannot be moved to another machine.
## Generating the activation request
The user enters their license key, and your app generates the offline activation request file at the path you pass to the function:
`GenerateOfflineActivationRequest()` creates the request file at the path you provide, so the path must include the file name.
## Creating the activation response
Take the request file to any machine with internet access. In the admin portal, open the `Activations` page, click **`CREATE OFFLINE`**, upload the offline activation request file, set the validity of the response file, and click **`ACTIVATE`**. If the request is valid, the offline activation response file can be downloaded.
The response file is valid only for the period you set, so it must be consumed on the offline machine before that period expires. On the admin portal you can configure this validity; on the customer portal it is fixed at 3 days.
Response validity is not the same as the license's expiration date. The expiration date is set on the license itself and enforced after activation as usual. Keep the response validity as short as your delivery workflow allows, since the file stays consumable on that machine for the full window.
An expired response file cannot be revived. If the validity period lapses before the offline machine consumes it, generate a new offline activation request on that machine and exchange it for a fresh response.
Your customers can also log in to the customer portal and download the response file themselves, which saves you time on product support. This is useful when the offline machine is isolated but the customer has internet access on another device.
## Automating the activation response
Besides the portals, you can generate the response programmatically through the [`POST /v3/activations/offline-activate`](https://cryptlex.com/reference/web-api/post-activations-offline-activate) endpoint, which is useful for building your own tooling, such as an internal utility a service engineer runs on a connected laptop. The request body takes the `licenseId`, the content of the offline activation request file as `offlineRequest`, and the `responseValidity` in seconds. The endpoint identifies the license by `licenseId`, not by its key; if your tooling only has the license key, resolve the ID first with a `GET /v3/licenses?key=` lookup.
The endpoint requires a Web API access token. Never embed the token in an application you ship to customers; call the endpoint from your own backend or an internal tool instead. See [personal access tokens](https://cryptlex.com/docs/integrations-and-automation/personal-access-tokens).
## Activating with the response
Move the response file to the offline machine and let your app consume it from the path you pass to the function:
`ActivateLicenseOffline()` consumes the response file at the path you provide, so the path must include the file name.
LexActivator persists the activation on disk in encrypted form. On every application start, it verifies the stored activation and confirms that the machine's current fingerprint still matches the fingerprint recorded in the activation data, so the license cannot be moved to another machine.
## Deactivating offline
To free a seat from a machine without internet access, generate an offline deactivation request at the path you pass to the function:
This invalidates the local license data and writes an offline deactivation request file, which the user sends to you. To release the seat, delete the corresponding activation from the `Activations` page in the admin portal.
## Controlling deactivations and transfers
For licenses that are activated offline, treat machine transfers as a deliberate, support-driven step rather than a self-service one:
* **Set Allowed Deactivations to 0** on the license, and raise it only when a customer legitimately requests a transfer to another machine. This keeps the number of transfers under your control.
* **Keep the response validity short**, as described above, so an issued response file cannot be consumed long after it was generated.
* **Route deactivation by activation mode.** If your app supports both online and offline activation, call `GetActivationMode()` to determine how the license was activated: use `DeactivateLicense()` for online activations and `GenerateOfflineDeactivationRequest()` for offline ones, so each activation is released through the flow it was created with.
## Offline floating licenses
Offline activation applies to node-locked licenses. A hosted floating license is not suitable for offline machines, because its lease must be renewed against the Cryptlex servers and the activation is removed when renewal fails. For floating licensing inside an offline network, deploy [LexFloatServer](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/overview) on the customer's premises.
For on-premise floating deployments, borrowing works differently, through LexFloatClient. See [Borrowing a license for offline use](https://cryptlex.com/docs/sdks-and-apis/lexfloatclient#borrowing-a-license-for-offline-use).
---
# Software Maintenance and Support
Section: Licensing Models
URL: https://cryptlex.com/docs/licensing-models/software-maintenance-and-support
Summary: Monetize your software updates with Cryptlex maintenance policies that gate update eligibility by version and duration, so customers pay to keep receiving updates and support.
Last updated: 2026-09-15
Software maintenance and support (also called a maintenance contract or AMC) lets you monetize your software updates: a customer keeps using the version they bought, but receives updates only while their maintenance is active. It is most useful with perpetual licenses, where you want recurring revenue from updates rather than from the license itself.
You offer it by creating a maintenance policy and linking it to a license, the same way feature entitlements and meter attributes layer onto a license. The policy controls which updates (major or minor) a customer can install, and for how long.
Maintenance policies work independently of Cryptlex [Release Management](https://cryptlex.com/docs/releases/overview). You can keep your existing distribution mechanism and still have Cryptlex enforce update eligibility, so adopting maintenance policies does not mean adopting Cryptlex releases.
## Maintenance policy properties
A maintenance policy has the following properties:
Property
Description
Name
Name of the maintenance policy.
Subscription Interval
How long updates stay available, as an ISO 8601 duration (`P1Y`, `P3M10D`, `P30D`), which accounts for varying month and year lengths. Set to `null` for lifetime maintenance.
Subscription Start Trigger
When the maintenance period begins: `license-creation` (aligns with the purchase date) or `license-activation` (starts on first activation).
Allow Major Version Updates
If `true`, major version updates are allowed until the license maintenance expires.
Allow Minor Version Updates
If `true`, minor version updates are allowed until the license maintenance expires.
## Enforcing update eligibility in your app
After you have created a maintenance policy and linked it to a license, call `SetReleaseVersion()` in your app (after `SetProductId()`) with your app's current version:
The version must be dot-separated digits in one of three forms: `$MAJOR.$MINOR`, `$MAJOR.$MINOR.$PATCH`, or `$MAJOR.$MINOR.$PATCH.$BUILD` (for example, `1.2`, `1.2.3`, or `1.2.3.4`).
If you do not use Cryptlex [Release Management](https://cryptlex.com/docs/releases/overview), also call `SetReleasePublishedDate()` so LexActivator knows when the release was published.
Call order matters. Call `SetReleaseVersion()` and `SetReleasePublishedDate()` **before** `IsLicenseValid()`, `IsLicenseGenuine()`, or any getter such as `GetLicenseMaintenanceExpiryDate()` (which validates the license internally). If a validation or getter function runs before the release version is set, the release checks are silently skipped and an out-of-maintenance version appears valid. The correct sequence is `SetProductData()`, `SetProductId()`, `SetReleaseVersion()`, `SetReleasePublishedDate()`, and only then validation and getter calls.
The version set here is stored in the license as the `currentReleaseVersion` property and in the activation as the `releaseVersion` property. If the license has more than one activation, `currentReleaseVersion` stores the maximum release version across activations.
## Renewing maintenance
A license linked to a maintenance policy with a `subscriptionInterval` exposes a read-only, computed `maintenanceExpiresAt` property, the date its maintenance expires. When it is set depends on the policy's `subscriptionStartTrigger`:
* **`license-creation`**: computed from the license creation date.
* **`license-activation`**: stays `null` until the first activation, since maintenance starts only when the license is used.
To renew, call the [license maintenance renew endpoint](https://cryptlex.com/reference/web-api/post-licenses-id-maintenance-renew) or use the license page in the admin portal. Renewal extends `maintenanceExpiresAt` by the policy's `subscriptionInterval`.
## Common configurations
Goal
subscriptionInterval
allowMajorVersionUpdates
allowMinorVersionUpdates
Lifetime free updates (or create no policy)
`null`
`true`
`true`
Lifetime minor version updates only
`null`
`false`
`true`
One year of all updates
`P1Y`
`true`
`true`
One year of minor version updates only
`P1Y`
`false`
`true`
No updates
`null`
`false`
`false`
## Limiting updates without a policy
If you only want to allow updates up to a specific version, you do not need a maintenance policy. Set the license's `maxAllowedReleaseVersion` property to the highest version you want to allow, and call `SetReleaseVersion("x.x.x")` in your app.
`maxAllowedReleaseVersion` gates which version may run, not which version may be downloaded. Your app reports its version through `SetReleaseVersion()` and LexActivator validates it against the cap, so a customer who obtains a newer build any other way still fails validation.
---
# Timed Trials
Section: Licensing Models
URL: https://cryptlex.com/docs/licensing-models/timed-trials
Summary: Offer timed trials with LexActivator so customers can evaluate your app before buying, with verified node-locked trials that cannot be reset, plus trial extensions.
Last updated: 2026-09-14
Timed trials let customers evaluate your app for a limited period before buying. A trial activation is keyless, so the user starts one without entering a license key. Cryptlex trials are verified and node-locked, so a trial does not reset if the user reinstalls your app or reformats the machine. Each trial activation appears in the admin portal under `Trials -> Trial Activations`.
Before trials will work, create a trial policy on the `Trials -> Trial Policies` page and link it to your product on the `Home -> Products` page. Only one trial policy can be linked to a product.
## How a trial works
1. **Start the trial** on first run with `ActivateTrial()`. Call it once, ideally on a button click, not on every start, since each call re-validates against the Cryptlex servers.
2. **Verify on every start** with `IsTrialGenuine()`, after your `IsLicenseGenuine()` check, and read the time left with `GetTrialExpiryDate()`. This works offline.
3. **If verification returns any other status**, the trial has either not been activated on this machine yet or could not be validated. `LA_FAIL` specifically means the trial has not been activated on this machine, so it is the signal to show your "Start Trial" action. Handle the returned status before deciding to call `ActivateTrial()`.
4. **When the trial expires**, the functions return `LA_TRIAL_EXPIRED`; prompt the user to buy a license.
Only some of these calls need the network. `ActivateTrial()` and `SyncTrialActivation()` reach the Cryptlex servers, while `IsTrialGenuine()` and `GetTrialExpiryDate()` validate the stored trial locally and work offline, so a trial extension does not apply until the machine syncs. Offline trial activations cannot be handled through the customer portal; host the [offline trial activation form](https://github.com/cryptlex/offline-trial-activation-form) instead.
## Trial fingerprint matching
When a trial is activated, the server matches the machine's fingerprint exactly, regardless of the configured [fingerprint matching strategy](https://cryptlex.com/docs/license-management/license-templates#fingerprint-matching-strategy). Calling `ActivateTrial()` again after a change in the machine's hardware configuration can therefore create a new trial activation with a fresh trial ID. `SyncTrialActivation()`, on the other hand, honors the fingerprint matching strategy for existing trials, so a minor hardware change does not prevent an already activated trial from syncing.
Never call `ActivateTrial()` to refresh an already activated trial, for example to pull an extended expiry date. Call `SyncTrialActivation()` instead: it syncs the existing trial activation with the server without any risk of creating a new one.
## Resetting a trial during development
Trials cannot be reset by your customers, but while testing your integration you will want to start fresh trials on your own machine. To reset a trial, delete its trial activation on the `Trials -> Trial Activations` page in the admin portal, then call the `Reset()` function in your app.
`Reset()` clears all locally stored LexActivator data for the product, not just the trial. If the machine also has an activated test license, call `DeactivateLicense()` first, otherwise its local record is wiped while the activation stays consumed on the server.
## Floating trials
Floating trials do not exist; trials are always node-locked. To let a customer evaluate floating licensing, create a floating license that expires after a short period, such as 30 days.
## Enforcing periodic server contact
Trials validate locally and work offline. To require server contact during an evaluation, call `SyncTrialActivation()` from your app at the interval you want. It refreshes the local trial data from the server, so server-side changes such as an updated expiry date or a deleted trial activation take effect on the machine.
## Extending a trial
You can extend a trial to give a customer more time to evaluate your product:
1. Ask the customer for their trial ID. Your app gets it with `GetTrialId()`.
2. In the admin portal, open `Trials -> Trial Activations`, search for the trial ID, and from the actions menu choose **`Update Expiration Date`**, pick the new date, and click **`Update`**.
3. In your app, call `SyncTrialActivation()` to pull the new expiry date to the client without reactivation. It also refreshes trial activation metadata if you have set any.
## Sample code
For the full flow and per-language samples, see [Using LexActivator](https://cryptlex.com/docs/sdks-and-apis/lexactivator).
---
# Containers and Virtual Machines
Section: Licensing Models
URL: https://cryptlex.com/docs/licensing-models/containers-and-virtual-machines
Summary: License apps in containers and virtual machines with Cryptlex, using node-locked licenses with crypto binding when online, or floating licenses served by LexFloatServer for offline environments.
Last updated: 2026-08-05
Containers and virtual machines can make device fingerprinting unreliable, so fingerprint-based node-locked licensing is a poor fit for apps deployed in them. Cryptlex recommends two approaches instead: floating licenses, or node-locked licenses with crypto binding. Both need an internet connection in the hosted setup; for offline environments, use floating licenses served by an on-premise LexFloatServer.
## Why device fingerprinting fails
### Containers
When an app runs inside a container, whether Docker, Kubernetes, or another runtime, it has very little access to the host hardware details, so it is difficult to generate a quality device fingerprint. If you use fingerprint-based node-locked licenses, your customers can use the same license key across different container instances running on the same or different devices.
### Virtual machines
Virtual machines expose virtualized hardware, and a VM can be cloned, which can result in multiple machines with the same device fingerprint. LexActivator detects virtual machines, and the [allow VM activations](https://cryptlex.com/docs/license-management/license-templates#allow-vm-activations) property lets you block activations inside VMs entirely if you prefer.
## Node-locked licenses with crypto binding
For containers and VMs with internet access, the recommended approach is to keep using node-locked licenses and enable crypto binding, by setting the `cryptoBindingEnabled` property on the [license template](https://cryptlex.com/docs/license-management/license-templates#crypto-binding) or the individual license. With crypto binding, the activation is bound cryptographically instead of relying on the device fingerprint, which reliably prevents a license key from being shared across container instances or cloned VMs, as long as an internet connection is available. Crypto binding is supported on Windows and Linux.
For containers, persist the activation data across container restarts by mounting a volume and pointing LexActivator's `SetDataDirectory()` function at it.
Without a mounted volume, every new container starts with no activation data, so it activates again and consumes another activation from the license. A deployment that recreates containers regularly will exhaust its allowed activations, which is the most common way container licensing goes wrong.
## Floating licenses
[Floating licenses](https://cryptlex.com/docs/licensing-models/floating-licenses/overview) are also a good option for containers and VMs, since seats are leased and freed dynamically instead of being tied to a device fingerprint:
* **Hosted floating**: for deployments with internet access, use the hosted-floating license type, with Cryptlex's servers acting as the license server. Set the [leasing strategy](https://cryptlex.com/docs/license-management/license-templates#leasing-strategy) to `per-instance` to consume a license activation for every running instance of your app, irrespective of whether the device fingerprint is the same or different.
* **On-premise floating**: for containers or VMs running in air-gapped, secured, or otherwise protected networks with no internet access, use the on-premise-floating license type with [LexFloatServer](https://cryptlex.com/docs/licensing-models/floating-licenses/on-premise-floating-licenses) running inside their network.
Floating licenses are the better choice when instances are short-lived or created automatically, such as Kubernetes pods or autoscaled workloads. A leased seat returns to the pool on its own, so ephemeral instances do not accumulate activations the way crypto binding does.
For help handling offline licensing inside containers or virtual machines, reach out to our [support channel](https://cryptlex.com/contact).
---
# Overview
Section: SDKs and APIs
URL: https://cryptlex.com/docs/sdks-and-apis/overview
Summary: Choose the right Cryptlex SDK or API for your app, from LexActivator for node-locked and hosted floating licenses to LexFloatClient for on-premise floating licenses.
Last updated: 2026-07-20
Cryptlex provides client libraries (SDKs) and REST APIs to integrate licensing into your app. Which one you need depends on the [licensing model](https://cryptlex.com/docs/licensing-models/choosing-a-licensing-model) you are implementing:
* **[LexActivator](https://cryptlex.com/docs/sdks-and-apis/lexactivator)** for node-locked, hosted floating, named-user licenses, and trials. It also supports offline activations.
* **[LexFloatClient](https://cryptlex.com/docs/sdks-and-apis/lexfloatclient)** with **[LexFloatServer](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/overview)** for floating licenses inside an air-gapped or otherwise restricted customer network.
* **[Web API](https://cryptlex.com/reference/web-api)** for integration and automation, such as creating licenses and users or processing orders.
## LexActivator
LexActivator is the main Cryptlex client library, used to implement node-locked, hosted floating, and named-user licenses, as well as trials. It validates licenses against the Cryptlex servers and handles HTTPS, response signature verification, encrypted local storage, machine fingerprinting, virtual machine detection, time tampering detection, periodic server sync, and offline activations for you.
It is available for Windows, macOS, Linux, Android, and iOS, with bindings for almost every major programming language. See [Using LexActivator](https://cryptlex.com/docs/sdks-and-apis/lexactivator).
## LexFloatClient & LexFloatServer
When a client application needs floating licenses but runs in an air-gapped, secured, or otherwise restricted network, it cannot reach the Cryptlex servers directly. For this, Cryptlex provides an on-premise floating license server, [LexFloatServer](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/overview), that your customer runs inside their own network. Your app requests and releases leases from LexFloatServer using the [LexFloatClient](https://cryptlex.com/docs/sdks-and-apis/lexfloatclient) library, and never contacts Cryptlex itself. LexFloatServer, in turn, may run connected to the Cryptlex servers or fully offline, depending on how it is configured.
## Web API
Everything in Cryptlex is available through the [REST Web API](https://cryptlex.com/reference/web-api). You can use it in two ways:
* **In your app**, as an alternative to LexActivator, to [activate and validate licenses directly](https://cryptlex.com/docs/sdks-and-apis/licensing-via-web-api), though this is not recommended. Use LexActivator wherever it is available for your platform.
* **On your server**, to automate license creation, user management, and order fulfillment, typically with [personal access tokens](https://cryptlex.com/docs/integrations-and-automation/personal-access-tokens).
Client machines connect to the Cryptlex servers over HTTPS. If your customers sit behind restrictive corporate networks, review [Proxies and Firewall](https://cryptlex.com/docs/sdks-and-apis/proxies-and-firewall).
While integrating, you can work against a [sandbox environment](https://cryptlex.com/docs/sdks-and-apis/sandbox-environments) to keep test data out of production.
## Minimum requirements
### LexActivator and LexFloatClient
The two client libraries you embed in your app share the same platform support.
Platform
Minimum version
Architectures
**Windows**
Windows 7 / Server 2008 or later
x86, x64, ARM64
**macOS**
macOS 10.13 or later
x86_64 (Intel), ARM64 (Apple Silicon)
**Linux**
glibc 2.13 or later
x86, x64, ARM, ARM64-v8a
**Android**
API level 23 or later*
ARMEABI-v7a, ARM64-v8a
**iOS**
iOS 11.0 or later
ARM64 (device); x86_64 (Intel) and ARM64 (Apple Silicon) simulators
* Building the Android library requires NDK r29e or later.
### LexFloatServer
The on-premise floating license server your customer runs on their own network.
Platform
Minimum version
Architectures
**Windows**
Windows 10 / Server 2016 or later
x86, x64
**macOS**
macOS 10.13 or later
x86_64 (Intel), ARM64 (Apple Silicon)
**Linux**
glibc 2.13 or later
x86, x64, ARM, ARM64-v8a
Earlier versions of LexFloatServer support Windows releases below Windows 10 and Server 2016.
Whichever path you choose, review the [best practices](https://cryptlex.com/docs/sdks-and-apis/best-practices) before shipping.
---
# LexActivator
Section: SDKs and APIs
URL: https://cryptlex.com/docs/sdks-and-apis/lexactivator
Summary: Integrate LexActivator into your app to activate, verify, and manage licenses, with code samples in every supported language.
Last updated: 2026-09-15
LexActivator is the Cryptlex client library you embed in your app to implement node-locked licenses, trials, hosted floating licenses, and named user licenses. This page shows you how to add the library to your app, activate and verify a license, and handle the hosted floating, named user, and offline activation flows, with code samples for every supported language.
## What LexActivator does for you
Under the hood, LexActivator is a libcurl based HTTP client that invokes the Cryptlex Web API endpoints from your application. You can invoke these endpoints with any HTTP library, but LexActivator does the hard parts for you:
* Abstracts away the HTTPS layer, so you call functions like `ActivateLicense()` and `ActivateTrial()` instead of sending HTTPS requests.
* Verifies the HTTPS response signature using an RSA public key.
* Stores the HTTPS response on disk in encrypted form using AES encryption, in a per-user or system-wide location depending on the permission flag you pass to `SetProductId()`. Where disk writes are restricted, it can instead keep the license data in memory, which requires activating the license again on each app restart and is typical for hosted floating licenses with a per-instance leasing strategy. See [activation data storage](#activation-data-storage) for the exact locations on each OS and how to change them.
* Generates multiple fingerprints of the machine using an advanced device fingerprinting algorithm, which allows for different fingerprint matching strategies.
* Detects virtual machines, so you can prevent users from activating your licenses in them (virtual machines can be cloned, which may result in the same fingerprint on different machines).
* Detects system clock tampering, so users cannot extend a time-limited license or trial by turning back the machine's clock.
* Periodically invokes the Cryptlex Web API endpoints in a separate thread to sync the server license data with the client.
* Handles offline activations.
## Minimum requirements
For the supported platforms, versions, and architectures, see [minimum requirements](https://cryptlex.com/docs/sdks-and-apis/overview#minimum-requirements).
## Adding licensing to your app
### Prerequisites
Before you integrate LexActivator, create a product for your app in the admin portal and create a [license](https://cryptlex.com/docs/license-management/overview) (node-locked or hosted floating) for it. Then, from the product's page, get the two things you will use in your code:
* The **Product ID** identifies your product in your code.
* The **Product.dat** file contains product data used by LexActivator. Download or copy it from the actions menu on the `Products` page.
`Product.dat` holds your product's RSA public key, which LexActivator uses to verify server responses, along with identifiers such as `productId` and `accountId`. It is meant to be embedded in your app.
For a complete, working integration in your language, refer to the [example projects on GitHub](https://github.com/cryptlex/lexactivator-examples).
### Adding the library to your app
C/C++/Objective-C
C#
VB.NET
Java
Python
Node.js
Go
Rust
Flutter
Android
Delphi
Ruby
iOS
Download the LexActivator library for Windows, macOS, or Linux from the [SDK downloads](https://app.cryptlex.com/developer/sdk-downloads) page. The package contains both the shared and static library.
Install the LexActivator package from [NuGet](https://www.nuget.org/packages/Cryptlex.LexActivator/):
Install the LexActivator package from [NuGet](https://www.nuget.org/packages/Cryptlex.LexActivator/):
The LexActivator wrapper for Java is on [Maven Central](https://search.maven.org/artifact/com.cryptlex.lexactivator/lexactivator). Add it to your POM file (use the latest version):
com.cryptlex.lexactivator
lexactivator
3.42.2
`} />
Alternatively, download the [JAR](https://repo1.maven.org/maven2/com/cryptlex/lexactivator/lexactivator/) file and add it to your project.
Install the LexActivator package from [pip](https://pypi.org/project/cryptlex.lexactivator/):
Install the LexActivator package from [npm](https://www.npmjs.com/package/@cryptlex/lexactivator):
Install the LexActivator wrapper with `go get`:
On Windows, copy `LexActivator.dll` from the `libs/windows_amd64` directory of the library package next to your executable.
This package uses `cgo` to interface with a C library, so `cgo` must be enabled when building. Disabling it (for example, `CGO_ENABLED=0`) causes compilation errors.
Add the LexActivator wrapper with Cargo:
Add the LexActivator wrapper with Flutter's package manager:
The LexActivator wrapper for Android is on [Maven Central](https://search.maven.org/artifact/com.cryptlex.android.lexactivator/lexactivator). Add it to your `build.gradle` file:
Alternatively, download the [AAR](https://repo1.maven.org/maven2/com/cryptlex/android/lexactivator/lexactivator/) file and add it to your project.
The Delphi example project (Delphi 7 or newer) contains the **LexActivator.pas** unit and the internally used **LexActivator.DelphiFeatures.pas** unit. Add both files to your app, but add only the LexActivator unit to the uses list. Depending on your target OS, copy the respective `LexActivator.dll`, `libLexActivator.so`, or `libLexActivator.dylib` to your project.
The Ruby example project contains the **LexActivator.rb** and **LexStatusCodes.rb** files, which include all the LexActivator API functions. Add these files to your project, and depending on your target OS, copy the respective `LexActivator.dll`, `libLexActivator.so`, or `libLexActivator.dylib` to your project.
Download the LexActivator library for iOS (in `.xcframework` format) from the [SDK downloads](https://app.cryptlex.com/developer/sdk-downloads) page, then add it to your project in Xcode. You can add either the dynamic or the static framework.
On older Windows versions (Windows 7, 8, or Server 2008/2012), LexActivator requires the Microsoft Visual C++ 2015 or later runtime. If it is not already installed, install the latest [Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist) or bundle the required DLLs with your installer.
### Setting the product data and product ID
Embed the product data (the contents of the `Product.dat` file) in your app using the `SetProductData()` function. Then set your product ID using the `SetProductId()` function.
Call both functions once during your app's initialization, before any activation or verification.
The contents of `Product.dat` can differ each time you download it, even when your product configuration has not changed. This is expected and does not mean your product settings changed. A copy you embedded earlier stays valid.
C/C++/Objective-C
C#
VB.NET
Java
Python
Node.js
Go
Rust
Flutter
Android
Delphi
Ruby
iOS
**Adding permissions**
The LexActivator library requires two permissions in the Android manifest.
`} />
**Setting the product data and product ID**
The permission flag you pass to `SetProductId()` determines where the activation data is stored:
* `LA_USER` (the default) stores the activation under the OS user who activated the license, so it is visible only to that user, and each OS user who runs the app activates separately. They all share the same seat. Enable [OS user-locked](https://cryptlex.com/docs/licensing-models/implementing-license-models#os-user-locked) to have each OS user consume a separate seat.
* `LA_ALL_USERS` stores the activation system-wide and shares it across all OS users on the machine. It is supported on Windows and macOS; on Linux, achieve the same result by pointing LexActivator at a system-wide directory with `SetDataDirectory()` and passing the `LA_ALL_USERS` flag.
* `LA_IN_MEMORY` keeps all data in memory instead of on disk. Use it when your app has no write access to the disk, and for [hosted floating licenses](https://cryptlex.com/docs/licensing-models/floating-licenses/hosted-floating-licenses) with a per-instance leasing strategy. Note that the license must be activated again every time the app restarts.
For the exact storage locations on each OS and how to handle environments with restricted storage, see [activation data storage](#activation-data-storage).
### License activation
Set the license key with `SetLicenseKey()`, then call `ActivateLicense()`. This assumes you have already set the product data and ID, as shown above. Call it when the user activates the license, for example on a button click. Use `SetLicenseKey()` and `ActivateLicense()` only in your activation flow, not during normal startup.
`ActivateLicense()` invokes the `/v3/activations` Web API endpoint and verifies the encrypted, digitally signed response to validate the license.
C/C++/Objective-C
C#
VB.NET
Java
Python
Node.js
Go
Rust
Flutter
Android
Delphi
Ruby
iOS
Result<(), LexActivatorError> {
set_license_key("PASTE_LICENSE_KEY".to_string())?;
match activate_license()? {
LexActivatorStatus::LA_OK |
LexActivatorStatus::LA_EXPIRED |
LexActivatorStatus::LA_SUSPENDED => {
println!("License activated successfully!");
}
status => {
println!("License activation failed with status: {:?}", status);
}
}
Ok(())
}`} />
### Verifying license activation
Each time your app starts, verify whether the license is already activated with `IsLicenseGenuine()`. This assumes the product data and ID are already set during initialization.
The check runs locally by verifying the cryptographic signature of the stored activation, so it works offline. LexActivator also syncs with the Cryptlex servers periodically in the background to pick up server-side changes such as renewals, suspension, or revocation.
C/C++/Objective-C
C#
VB.NET
Java
Python
Node.js
Go
Rust
Flutter
Android
Delphi
Ruby
iOS
Result<(), LexActivatorError> {
match is_license_genuine()? {
LexActivatorStatus::LA_OK |
LexActivatorStatus::LA_EXPIRED |
LexActivatorStatus::LA_SUSPENDED |
LexActivatorStatus::LA_GRACE_PERIOD_OVER => {
println!("License is genuinely activated!");
}
status => {
println!("License is not activated. Status: {:?}", status);
}
}
Ok(())
}`} />
## Hosted floating licenses
LexActivator implements hosted floating licenses the same way as node-locked licenses; the only difference is how you activate and release seats. A floating seat is held while your app runs and must be released on exit, otherwise it becomes a [zombie](https://cryptlex.com/docs/licensing-models/floating-licenses/overview#zombie-licenses) that keeps consuming a seat.
Validate the license first, activate based on the validation status, and release the seat on exit only for hosted floating licenses:
For when to choose hosted floating and how to configure the license template, see [hosted floating licenses](https://cryptlex.com/docs/licensing-models/floating-licenses/hosted-floating-licenses).
## Named user licenses
Named user licenses (also known as identity-based or user-locked licensing) can be implemented with LexActivator: the user logs in with their own credentials and their linked license is activated, instead of entering a license key. See [named user licenses](https://cryptlex.com/docs/licensing-models/named-user-licenses/overview) for the full activation flow and portal setup.
## Offline activation
LexActivator can activate licenses on machines with no internet access, using an offline activation request and response file pair. For the full walkthrough, see [offline activations](https://cryptlex.com/docs/licensing-models/offline-licenses).
## Server sync
Changes you make to a license on the server, such as extending, suspending, or revoking it, or updating its metadata or feature entitlements, do not reach an activated machine instantly. LexActivator verifies the license locally and picks up server-side changes through a periodic background sync. This section explains when a change reaches the client and how to react to it in your app.
### How server sync works
Local verification and server sync are two separate mechanisms:
* **Local verification is synchronous and offline.** `IsLicenseGenuine()` verifies the cryptographic signature of the locally stored activation data and returns immediately, without contacting the Cryptlex servers.
* **Server sync is asynchronous and periodic.** The first time `IsLicenseGenuine()` is called after your app starts, LexActivator triggers a server sync in a separate background thread, about 3 seconds later. Further syncs repeat at the [server sync interval](https://cryptlex.com/docs/license-management/license-templates#server-sync-interval) configured in the license template, for as long as the app runs.
A successful sync updates the local activation data with the current server-side state of the license. The result of every sync, whether the state changed or the sync failed, is delivered to the callback you register with `SetLicenseCallback()`.
`IsLicenseGenuine()` itself never blocks on the network and never returns the outcome of a sync that happens later in the run. To react to a change that arrives mid-session, use the license callback. To pull server-side changes on demand, call `SyncLicenseActivation()`, which performs a one-time synchronization and refreshes the local license data immediately, without waiting for the next periodic sync.
### When a change reaches the client
Every server-side change follows the same rule: it takes effect on the server immediately and reaches the activated machine on its next sync, or right away when your app calls `SyncLicenseActivation()`. This applies to extending, suspending, resuming, or revoking the license, updating its metadata or feature entitlements, and deleting the activation in the admin portal. Until that sync happens, the machine keeps running on its last synced state. The one exception is `DeactivateLicense()` called on the machine itself, which removes the local activation data on the spot.
Machines that are [offline](https://cryptlex.com/docs/licensing-models/offline-licenses) never sync, so no server-side change reaches them on its own. To deliver a change, such as an extended expiration date, repeat the offline activation flow: generate a new request file on the machine and consume a freshly generated response file.
### Registering the license callback
The callback registered with `SetLicenseCallback()` is tied to the license key, so the key must be set before the callback can be registered:
* In the first-run activation flow, call `SetLicenseCallback()` after `SetLicenseKey()` and before `ActivateLicense()`.
* On later runs, when the license is already activated, the key is already stored, so call `SetLicenseCallback()` before `IsLicenseGenuine()`.
* If the callback is registered more than once, the last registration before a sync wins.
The callback is invoked from the background sync thread, not your main thread. Do not touch UI elements from it directly; marshal back to the main thread using your framework's mechanism.
### How revocation appears in your app
When a license is [revoked](https://cryptlex.com/docs/license-management/suspending-and-revoking-licenses) server-side, the sync deletes the activation data on the machine. From then on, `IsLicenseGenuine()` returns `LA_FAIL`, meaning no activation, rather than `LA_E_REVOKED`. To tell a revoked license apart from a machine that was never activated, call `GetLastActivationError()`, which returns the error code that caused the activation data to be cleared, `LA_E_REVOKED` in this case. The license callback also receives `LA_E_REVOKED` during the session in which the revocation arrives, and `ActivateLicense()` returns it if the user tries to activate a revoked key again.
Suspension behaves differently: the activation data stays on the machine, `IsLicenseGenuine()` returns `LA_SUSPENDED`, and access is restored automatically on the sync after you resume the license.
### The in-memory cache
LexActivator serves reads from an in-memory cache that is populated when the library is first used in a process. If a different process activates the license, for example a service or installer activating on behalf of your app, a process that has already called `IsLicenseGenuine()` does not see the new activation until it restarts.
### Sync failure and the grace period
A sync that fails due to a network error does not invalidate the license. The [server sync grace period](https://cryptlex.com/docs/license-management/license-templates#server-sync-grace-period) in the license template defines how long sync failures are tolerated; once exceeded, verification returns `LA_GRACE_PERIOD_OVER` until a sync succeeds. Set the grace period to `-1` for machines that are rarely or never online, or to a finite value to force the machine to reconnect periodically.
The grace period applies to node-locked licenses. It has no meaningful effect on floating licenses: if a hosted floating lease fails to renew due to a network error, the activation is removed from the machine immediately, and the seat is freed on the server when the lease expires.
## Activation data storage
After a successful activation, LexActivator persists the activation data on the machine in encrypted form using AES encryption, and verifies it locally on every later run. Where it is stored depends on the OS and on the permission flag you pass to `SetProductId()`:
* **`LA_USER`** stores the data in the current user's profile: the registry on Windows, and a per-user application data directory on macOS and Linux.
* **`LA_ALL_USERS`** stores the data in a system-wide location shared by every user of the machine. On Linux, there is no default system-wide location, so set one with `SetDataDirectory()`.
Call `GetDataStoreInfo()` to get the exact location LexActivator is using on the current machine, which is useful when debugging a license that appears to be lost.
With the `LA_IN_MEMORY` flag, nothing is written to disk at all; the activation data lives only in memory and the license must be activated again on every app restart.
The per-user locations are resolved from the account your app actually runs as. A process running under `sudo`, a service account, or a different OS user reads and writes that user's home directory or registry hive, not the logged-in user's, which is a common cause of a license appearing to be "lost".
Activation data is stored per product. Multiple Cryptlex-licensed applications on the same machine, including products from other vendors, never interfere with each other's activation data, even though they share these locations.
### Changing the storage location
Call `SetDataDirectory()` to store the activation data in a directory of your choice instead of the default location:
Three rules apply:
* Call it at every start of your app, **before** `SetProductData()` and `SetProductId()`.
* The directory must already exist, and your app must have read and write permissions in it.
* It works on the file-based platforms: macOS, Linux, and Android. On Windows, `LA_USER` activation data always lives in the registry, so the function does not apply there.
### Restricted environments
If LexActivator cannot write to the default location, `SetProductData()` or `SetProductId()` fails with `LA_E_SYSTEM_PERMISSION` ("Insufficient system permissions"), or the activation succeeds but is not found on the next run, so the app asks for the license key again. The fix in every case is to point `SetDataDirectory()` at a location your app is allowed to write to:
* **macOS App Sandbox:** apps using Apple's App Sandbox, including everything distributed through the Mac App Store and plugins whose host app uses it, cannot write to `~/Library/Application Support` directly. Add the `com.apple.security.network.client` entitlement so LexActivator can reach the Cryptlex servers, and call `SetDataDirectory()` with a path inside your app's container.
* **Android:** Android apps, including Unity and other engine-based builds, must store the data in the app's own storage area. In Unity, pass `Application.persistentDataPath` to `SetDataDirectory()`. The library also requires the `android.permission.INTERNET` and `com.google.android.providers.gsf.permission.READ_GSERVICES` permissions in the manifest.
* **Linux services and non-login users:** a process running as a user without a home directory, such as a daemon under a service account or a binary invoked from a web server, has no writable default location. Either create a home directory for that user or call `SetDataDirectory()` with a directory the service account can write to.
* **No writable storage at all:** pass the `LA_IN_MEMORY` permission flag to `SetProductId()` instead. The license must then be activated again on every app restart, which is the standard setup for [hosted floating licenses with a per-instance leasing strategy](https://cryptlex.com/docs/license-management/license-templates#leasing-strategy).
### Cleaning up on uninstall
To remove the activation data when your app is uninstalled, call the `Reset()` function from your uninstaller. It clears the stored activation data for your product only.
Never delete the shared storage locations themselves. They can contain activation data belonging to other Cryptlex-licensed products installed on the machine. `Reset()` is always the safe way to clean up.
`Reset()` removes only the local data; it does not release the activation on the Cryptlex servers. To free up the seat as well, call `DeactivateLicense()` before `Reset()`.
## Next steps
- Review the [best practices](https://cryptlex.com/docs/sdks-and-apis/best-practices) for permission flags and license verification.
- Use [feature entitlements](https://cryptlex.com/docs/features-and-entitlements/overview) to control feature access per license, and retrieve them at runtime as described in [Accessing Feature Entitlements](https://cryptlex.com/docs/features-and-entitlements/accessing-feature-entitlements).
- Support air-gapped customers with [offline activations](https://cryptlex.com/docs/licensing-models/offline-licenses).
- Implement [hosted floating licenses](https://cryptlex.com/docs/licensing-models/floating-licenses/hosted-floating-licenses) or [timed trials](https://cryptlex.com/docs/licensing-models/timed-trials).
- Deliver updates to licensed users with [auto-updates](https://cryptlex.com/docs/releases/auto-updates).
- Handle restrictive customer networks with [proxies and firewall whitelisting](https://cryptlex.com/docs/sdks-and-apis/proxies-and-firewall).
## Need more help?
If you need more help adding LexActivator to your app, we'll be glad to help with the integration. Contact us through the [contact page](https://cryptlex.com/contact).
---
# LexFloatClient
Section: SDKs and APIs
URL: https://cryptlex.com/docs/sdks-and-apis/lexfloatclient
Summary: Integrate LexFloatClient into your app to request, renew, and drop floating licenses from LexFloatServer, with code samples in every supported language.
Last updated: 2026-07-21
LexFloatClient is used in client applications to obtain floating licenses from [LexFloatServer](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/overview). It handles the process of requesting, renewing, and dropping license leases in your app. Before integrating LexFloatClient, make sure the LexFloatServer is [installed](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/installing-lexfloatserver), [configured](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/configuring-and-startup), and [activated](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/activating-the-lexfloatserver) on your customer's network.
## Minimum requirements
For the supported platforms, versions, and architectures, see [minimum requirements](https://cryptlex.com/docs/sdks-and-apis/overview#minimum-requirements).
## Adding licensing to your app
### Prerequisites
After you have added a product for your app in the admin portal, note its **Product ID** from the actions menu on the `Products` page. You will use this product ID in your code, and it must match the product ID configured in LexFloatServer.
For a complete, working integration, refer to the [example project on GitHub](https://github.com/cryptlex/lexfloatclient-examples).
### Adding the library to your app
C/C++/Objective-C
C#
VB.NET
Java
Python
Node.js
Go
Android
Delphi
iOS
Download the LexFloatClient library for Windows, macOS, or Linux from the [SDK downloads](https://app.cryptlex.com/developer/sdk-downloads) page. The package contains both the shared and static library.
Install the LexFloatClient wrapper for C# from [NuGet](https://www.nuget.org/packages/Cryptlex.LexFloatClient):
or
Install the LexFloatClient wrapper for VB.NET from [NuGet](https://www.nuget.org/packages/Cryptlex.LexFloatClient):
or
The LexFloatClient wrapper for Java is available on the [central Maven repository](https://search.maven.org/artifact/com.cryptlex.lexfloatclient/lexfloatclient). Add the following dependency to your POM file (use the latest version):
com.cryptlex.lexfloatclient
lexfloatclient
4.16.1
`} />
Alternatively, download the [JAR](https://repo1.maven.org/maven2/com/cryptlex/lexfloatclient/lexfloatclient/) file and add it to your project.
Install the LexFloatClient wrapper for Python from [pip](https://pypi.org/project/cryptlex.lexfloatclient/):
Install the LexFloatClient wrapper for Node.js from [npm](https://www.npmjs.com/package/@cryptlex/lexfloatclient):
Install the LexFloatClient wrapper for Go with the `go get` command:
On Windows, copy `LexFloatClient.dll` from the `libs/windows_amd64` directory of the downloaded library package next to your executable.
This package relies on `cgo` to interface with a C library, so `cgo` must be enabled when building. Disabling it (for example, `CGO_ENABLED=0`) causes compilation errors.
The LexFloatClient wrapper for Android is available on the [central Maven repository](https://search.maven.org/artifact/com.cryptlex.android.lexfloatclient/lexfloatclient). Add the following dependency to your `build.gradle` file:
Alternatively, download the [AAR](https://repo1.maven.org/maven2/com/cryptlex/android/lexfloatclient/lexfloatclient/) file and add it to your project.
Download the LexFloatClient library for Windows from the [SDK downloads](https://app.cryptlex.com/developer/sdk-downloads) page.
The Delphi example project (Delphi 7 or newer) contains the **LexFloatClient.pas** unit and the internally used **LexFloatClient.DelphiFeatures.pas** unit. Add both files to your project, but add only the LexFloatClient unit to the uses list.
Download the LexFloatClient library for iOS (in `.xcframework` format) from the [SDK downloads](https://app.cryptlex.com/developer/sdk-downloads) page, then add it to your project in Xcode. You can add either the dynamic or the static framework.
The `.xcframework` supports the following architectures:
* iOS Simulator: `x86_64` (Intel), ARM64 (Apple Silicon)
* iOS: ARM64
On older Windows versions (Windows 7, 8, or Server 2008/2012), LexFloatClient requires the Microsoft Visual C++ 2015 or later runtime. If it is not already installed, install the latest [Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist) or bundle the required DLLs with your installer.
### Requesting a floating license
Set the host product ID, the LexFloatServer address, and a callback for status notifications, then request a license lease from the server. Run this whenever the user starts the app or needs a new license.
C/C++/Objective-C
C#
VB.NET
Java
Python
Node.js
Go
Android
Delphi
iOS
The second argument of `LexFloatClient.SetFloatingLicenseCallback` is `False` because console applications have no message loop. In GUI applications, setting `Synchronized` to `True` is recommended to enforce execution in the main thread.
### Renewing a floating license
The license lease renews automatically in a background thread. Whenever it renews or fails to renew, your callback is invoked from that thread.
C/C++/Objective-C
C#
VB.NET
Java
Python
Node.js
Go
Android
Delphi
iOS
Whenever the lease renews or fails to renew, the callback is invoked (from the background thread). The `Error` argument is `nil` when the lease has renewed successfully and holds the exception when renewal failed. The callback can be a procedure, an object method, a class method, or a closure (also known as an anonymous function). Note that GUI applications cannot safely interact with GUI elements from a thread other than the GUI thread. `System.Classes.TThread.Synchronize` will be used if `Synchronized` was `True` when the callback was set. However, `Synchronized` cannot work without a message loop in the main thread (for example, in console applications), so synchronization must be performed in another way in that case.
You would ideally request a new license if the callback reports a renewal failure (`Error` is not `nil`).
### Dropping a floating license
When the user is done, free the license so it becomes available to others. If you don't, the license stays leased (a zombie) until the lease expires. Run this whenever the user closes the app.
C/C++/Objective-C
C#
VB.NET
Java
Python
Node.js
Go
Android
Delphi
iOS
GUI applications (such as VCL) are supposed to divide the code into initialization and finalization. `LexFloatClient.ResetFloatingLicenseCallback` should be called before the callback becomes invalid. For example, a form method becomes invalid after the form is destroyed, so `TForm.OnDestroy` is a proper place to call `ResetFloatingLicenseCallback`. `LexFloatClient.DropFloatingLicense` should also be invoked, but beware of exceptions it can raise. Sample code:
### Borrowing a license for offline use
Borrowing (also known as an offline floating license) lets a user keep using licensed functionality while disconnected from LexFloatServer, for a set duration after which it expires automatically. The LexFloatServer administrator caps the lease duration with `maxOfflineLeaseDuration` and the number of clients that can hold an offline lease at once with `allowedOfflineFloatingClients`, both in `config.yml`.
Call `RequestOfflineFloatingLicense()` with the lease duration the client wants to borrow for, up to that maximum. Check for an existing lease with `HasFloatingLicense()` before requesting one. The license stays valid while the user is disconnected and expires automatically when the duration elapses.
For how this fits the licensing model, see [on-premise floating licenses](https://cryptlex.com/docs/licensing-models/floating-licenses/on-premise-floating-licenses).
## Next steps
- See how the on-premise floating model works in [On-Premise Floating Licenses](https://cryptlex.com/docs/licensing-models/floating-licenses/on-premise-floating-licenses).
- Query the server's status and leases with the [LexFloatServer API endpoints](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/lexfloatserver-api-endpoints).
## Need more help?
If you need more help adding LexFloatClient to your app, we'll be glad to help you with the integration. Contact us through the [contact page](https://cryptlex.com/contact).
---
# Overview
Section: SDKs and APIs > LexFloatServer
URL: https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/overview
Summary: Download LexFloatServer for Windows, macOS, or Linux to serve floating licenses inside your customers' networks.
Last updated: 2026-09-14
LexFloatServer is the licensing server software that leases floating licenses to your app. It is typically installed on a computer in your customer's local network. If you have multiple products, each product requires its own instance of LexFloatServer.
LexFloatServer is lightweight and fast, so it runs well even on an old machine connected to the local network.
LexFloatServer requires the Microsoft Visual C++ runtime, which is included by default on newer Windows versions. Only on older Windows versions do you need to install the latest [Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist) before running the server.
## Deployment considerations
* **Where to run the server.** LexFloatServer is node-locked to the machine it runs on, and its multi-process detection stops a second instance from starting on the same host, whether or not the host is online. If the host has internet access, the server can run anywhere, including inside a virtual machine or container, because it keeps validating its own license against the Cryptlex servers. In an offline or air-gapped network, the device fingerprint alone has to prevent clones, so choose the host accordingly: a physical machine is the safe default, a cloud VM also works well because cloud providers expose unique instance identifiers that make the fingerprint reliable, and a container running inside a Kubernetes cluster fingerprints reliably too. Avoid offline on-premises VMs that can be cloned freely, since a clone could lease seats from a single license undetected. Your licensed app, as a floating client, can always [run inside containers and VMs](https://cryptlex.com/docs/licensing-models/containers-and-virtual-machines).
* **There is no built-in high availability or failover.** LexFloatServer continuously persists its lease state on disk, so after a crash or reboot it comes back knowing which licenses are leased. To ride out short outages, set the lease duration long enough that clients keep running on their current lease while the server machine recovers.
## Minimum requirements
For the supported platforms, versions, and architectures, see [minimum requirements](https://cryptlex.com/docs/sdks-and-apis/overview#minimum-requirements).
## Downloading LexFloatServer
You can download LexFloatServer from the [SDK Downloads](https://app.cryptlex.com/developer/sdk-downloads) page in the admin portal. Binaries are available for Windows, macOS, and Linux.
---
# Installation
Section: SDKs and APIs > LexFloatServer
URL: https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/installing-lexfloatserver
Summary: Install, start, stop, and uninstall LexFloatServer as a service on Windows, Linux, and macOS.
Last updated: 2026-07-13
## Installing LexFloatServer on Windows
LexFloatServer runs as a service on Windows. To install it as a service, pass the `-i` option along with a service name and optionally a service display name, which is shown in the Windows Services Manager:
After installation, it is set to start with the computer and run silently in the background.
### Stopping and starting LexFloatServer on Windows
To stop or start the server from the command line, you need the service name. If the service name was not passed during installation, it defaults to `lexfloatserver-productId` (where product id is the id of your product):
### Uninstalling LexFloatServer on Windows
To uninstall, first pass the `-d` option to deactivate the server license, then the `-u` option to remove the service:
## Installing LexFloatServer on Linux
LexFloatServer can run as a systemd, Upstart, or SysV service on Linux. To install it as a service, pass the `-i` option along with the service name:
After installation, it is set to start with the computer and run silently in the background.
### Stopping and starting LexFloatServer on Linux
To stop or start the server from the command line, you need the service name. If the service name was not passed during installation, it defaults to `lexfloatserver.productId` (where product id is the id of your product):
### Uninstalling LexFloatServer on Linux
To uninstall, first pass the `-d` option to deactivate the server license, then the `-u` option to remove the daemon:
## Installing LexFloatServer on macOS
LexFloatServer runs as a launchd daemon on macOS. To install it as a service, pass the `-i` option along with the service name:
After installation, it is set to start with the computer and run silently in the background.
### Stopping and starting LexFloatServer on macOS
To stop or start the server from the command line, you need the service name. If the service name was not passed during installation, it defaults to `com.lexfloatserver.productId` (where product id is the id of your product):
### Uninstalling LexFloatServer on macOS
To uninstall, first pass the `-d` option to deactivate the server license, then the `-u` option to remove the daemon:
---
# Configuration and Startup
Section: SDKs and APIs > LexFloatServer
URL: https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/configuring-and-startup
Summary: Configure LexFloatServer through its config.yml file and start it from the command line.
Last updated: 2026-07-13
## Configuring the LexFloatServer
LexFloatServer reads its configuration from a YAML file. It expects a `config.yml` file in the same directory as LexFloatServer. If the config file is in another directory, pass its path using the `-c` option.
The config is loaded when the server starts. Changes to the config file take effect only after the server is restarted.
## Starting LexFloatServer in the terminal
For testing, you can run LexFloatServer in the terminal (command prompt). To start the server, pass the `-s` option:
You need admin rights to run LexFloatServer.
---
# Activation
Section: SDKs and APIs > LexFloatServer
URL: https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/activating-the-lexfloatserver
Summary: Activate LexFloatServer with an on-premise floating license key using its local dashboard, the CLI, or its API endpoints, online or offline.
Last updated: 2026-08-25
LexFloatServer needs to be activated using a license of type **on-premise-floating** before it can be used. It can be activated using its local dashboard, command-line options, or its API endpoints.
Set the [server sync grace period](https://cryptlex.com/docs/license-management/license-templates#server-sync-grace-period) to `-1` on the on-premise-floating license you use to activate LexFloatServer. Air-gapped networks have no internet access, so syncs with Cryptlex keep failing, and an unlimited grace period keeps the server leasing seats regardless.
## Using the local dashboard
LexFloatServer provides a web-based local dashboard that can be used to activate the server license.
### Online activation
Open the dashboard by visiting `http://localhost:8090` in your browser. Go to the `Settings` page and enter the license key to activate the server.
### Offline activation
To activate offline, click **`SWITCH TO OFFLINE ACTIVATION`** on the `Settings` page. Enter the license key to generate the offline activation request file.
After generating the offline response from the Cryptlex admin portal for this request, paste the offline response file contents in the input to activate the server.
## Using command-line options
### Online activation
To activate, pass the `-a` option along with the license key. If the product file path is not set in the `config.yml` file, pass it too using the `--product-file` option:
### Offline activation
To activate offline, pass the `-g` option to generate the offline activation request:
After generating the offline response from the admin portal, pass it along with the `-a` option to activate the server:
### Offline deactivation
To deactivate an offline-activated server, pass the `-d` option along with the `--offline-request` option:
The local activation is removed immediately, and the command writes an offline deactivation request file. Upload that file in the admin portal to release the activation on the server side. Passing `-d` without `--offline-request` performs an online deactivation instead.
## Using the API endpoints
LexFloatServer exposes a few API endpoints that can also be used to activate the server.
### Online activation
Send a POST request to the `/api/server/activate` API endpoint with a JSON request body containing the license key and optionally the activation metadata.
#### Request body
Name
Type
Description
licenseKey
string
License key to activate the server.
metadata
array
Activation metadata.
Sample response:
200
400
### Offline activation
Send a POST request to the `/api/server/offline-activation-request` API endpoint with a JSON request body containing the license key and optionally the activation metadata.
#### Generate the offline activation request
#### Request body
Name
Type
Description
licenseKey
string
License key to activate the server.
metadata
array
Activation metadata.
After generating the offline response from the admin portal, send a POST request to the `/api/server/offline-activate` API endpoint with a JSON request body containing the license key and the offline response.
#### Activate the server offline
#### Request body
Name
Type
Description
licenseKey
string
License key to activate the server.
offlineResponse
string
Offline activation response.
Sample response:
200
400
## Applying license changes to an offline-activated server
A LexFloatServer activated offline holds the license data from the response file it consumed, so nothing you change on the license in the admin portal reaches it on its own. A renewal, a change to the allowed floating clients, suspension, or revocation applies only once the server picks up new license data, in one of two ways:
* **Exchange a fresh offline request and response.** Generate a new offline activation request on the server, create a response for it in the admin portal, and apply it, exactly as you did when activating the server.
* **Give the machine temporary internet access.** LexFloatServer then syncs with Cryptlex and pulls the changes at its next sync. Restart LexFloatServer to sync immediately instead of waiting for the next one.
---
# API Endpoints
Section: SDKs and APIs > LexFloatServer
URL: https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/lexfloatserver-api-endpoints
Summary: LexFloatServer HTTP endpoints for server stats, license details, leased floating licenses, meter attributes, and feature entitlements.
Last updated: 2026-07-13
LexFloatServer provides several API endpoints for retrieving information related to its status, license details, leased floating licenses, meter attributes, and feature entitlements.
These are protected endpoints and require an `apiKey` to be included as a query parameter in the request URL. The `apiKey` can be configured in the `config.yml` file under the `auth` section of LexFloatServer.
## Getting server stats
LexFloatServer exposes a stats API endpoint that can be used to get the current stats of the server.
Sample response:
## Getting server license info
LexFloatServer exposes a license info API endpoint that can be used to get the information related to the license used to activate the LexFloatServer.
Sample response:
## Getting the list of floating licenses
LexFloatServer exposes a floating-licenses API endpoint that can be used to get the leased floating licenses.
Sample response:
## Getting server license meter attributes
LexFloatServer exposes a license meter attributes API endpoint that can be used to get the list of all the meter attributes of the license used to activate the LexFloatServer.
Sample response:
## Getting server license feature entitlements
LexFloatServer exposes a feature entitlement API endpoint that can be used to get the list of all the feature entitlements associated with the license used to activate the LexFloatServer.
Sample response:
---
# Licensing via Web API
Section: SDKs and APIs
URL: https://cryptlex.com/docs/sdks-and-apis/licensing-via-web-api
Summary: Activate, verify, sync, and deactivate licenses in your app using the Cryptlex Web API with JWT tokens and RSA signature verification.
Last updated: 2026-07-13
We **strongly** recommend using the [LexActivator](https://cryptlex.com/docs/sdks-and-apis/lexactivator) library for licensing. Use the Web API for license activation only if LexActivator is not available for your OS.
## Prerequisites
After you have added a product for your app in the admin portal, go to that product's page. You will need to do two things:
* Note the product id.
* Download the RSA public key for the product.
The RSA public key is needed to verify the signature of the activation token you receive on activating a license. The product id identifies the product to be licensed.
The license's [`fingerprintMatchingStrategy`](https://cryptlex.com/docs/license-management/license-templates#fingerprint-matching-strategy) applies only to fingerprints generated by a Cryptlex SDK, so it is ignored when you license through the Web API.
## Activation lifecycle
Once setup is complete, your app manages the license through the following calls.
### Activating the license
To activate the license in your app using the license key, send a `POST` request to the create activation endpoint. Refer to the [`POST /v3/activations`](https://cryptlex.com/reference/web-api/post-activations) reference for endpoint details.
On successful activation, the endpoint returns an activation token. The activation token is a [JWT](https://jwt.io/), so you can verify its signature using any JWT library available for your language. You can then parse the JWT activation token to get the license details.
If your product uses [feature entitlements](https://cryptlex.com/docs/features-and-entitlements/overview), note that they are not part of the activation token. Fetch them separately by sending a `GET` request to the [`GET /v3/activations/:id/feature-entitlements`](https://cryptlex.com/reference/web-api/get-activations-id-feature-entitlements) endpoint, passing `accountId` and `licenseId` as query parameters.
### Verifying license activation
Each time your app starts, verify whether the license is already activated. This verification should happen locally by verifying the signature of the JWT activation token using the RSA public key.
Storing the JWT activation token and feature entitlements in encrypted form is recommended, though not required unless the token contains sensitive metadata.
Once the signature is verified, parse the token to read the license details.
If the license has feature entitlements linked, the feature entitlements response is also a signed JWT. Verify its signature with the same RSA public key, then parse it to read the entitlements.
### Syncing license activation
To sync the client changes with the server and vice versa, send a `PATCH` request periodically to the update activation endpoint. You can decide the sync frequency yourself, or use the sync interval set for the license (available in the JWT activation token). If you choose the latter, you can control it from the admin portal. Refer to the [`PATCH /v3/activations/:id`](https://cryptlex.com/reference/web-api/patch-activations-id) reference for endpoint details.
If your product uses feature entitlements, fetch them again from the [`GET /v3/activations/:id/feature-entitlements`](https://cryptlex.com/reference/web-api/get-activations-id-feature-entitlements) endpoint after each sync, since they may have changed on the server.
### Deactivating a license
To deactivate the activation on the machine, send a `POST` request to the deactivate activation endpoint. Refer to the [`POST /v3/activations/:id/deactivate`](https://cryptlex.com/reference/web-api/post-activations-id-deactivate) reference for endpoint details.
## Authenticating users
For user-based flows such as [named user licensing](https://cryptlex.com/docs/licensing-models/named-user-licenses/overview), authenticate the user with the [login endpoint](https://cryptlex.com/reference/web-api/post-accounts-login) to obtain an access token. With that token you can call user-scoped endpoints on behalf of the user, such as fetching their licenses via the `/v3/me/licenses` endpoint, or build a custom self-service experience instead of the [customer portal](https://cryptlex.com/docs/customers/customer-portal).
---
# Proxies and Firewall
Section: SDKs and APIs
URL: https://cryptlex.com/docs/sdks-and-apis/proxies-and-firewall
Summary: How LexActivator detects proxies automatically, how to set a custom proxy, and which domains to whitelist in firewalls.
Last updated: 2026-07-13
## Proxies
LexActivator automatically detects the proxy settings of the machine. So, in most cases, you don't need to worry about whether your user is behind a proxy server.
To detect proxy settings, it uses the standard methods available for each operating system. On Windows, it checks the system proxy settings; on macOS, it reads proxy settings from the system internet settings; and on Linux, it reads proxy settings from the environment variable `http_proxy`.
### Custom proxy settings
You can allow the user to set the proxy settings to be used by LexActivator with the following LexActivator function:
The proxy format should be:
`[protocol://][username:password@]machine[:port]`
Some examples of valid proxy strings:
* `http://127.0.0.1:8000/`
* `http://user:pass@127.0.0.1:8000/`
* `socks5://127.0.0.1:8000/`
## Firewall whitelisting
If the security policy at your customer's end blocks access to external IP addresses and websites, license and trial activations will fail unless the Cryptlex IP addresses and Web API URL are whitelisted in the firewall.
### Access through firewall
Ask your customer to whitelist the IP addresses and Web API URL for the data center your account uses.
Data center
IP addresses to whitelist
Web API URL to whitelist
US (default)
`52.223.22.71`
`35.71.188.31`
`https://api.cryptlex.com:443`
EU
`75.2.113.112`
`99.83.149.57`
`https://api.eu.cryptlex.com:443`
---
# Sandbox Environments
Section: SDKs and APIs
URL: https://cryptlex.com/docs/sdks-and-apis/sandbox-environments
Summary: Test your Cryptlex integration in an isolated sandbox environment with its own copy of all licensing data, without touching production.
Last updated: 2026-08-11
Sandbox environments let you build and test your licensing integration in isolation from production. Each account has one production environment and one or more sandbox environments; how many depends on your plan. Everything you create in a sandbox stays in that sandbox, so your developers can experiment freely without polluting production data or metrics.
## What a sandbox isolates
Each environment holds its own independent copy of your licensing data:
* Products, license templates, licenses, activations, and trial activations.
* Users, organizations, features, Entitlement Sets, and meter attributes.
* Releases and release files.
* Webhooks, automated email templates, and personal access tokens.
Names are independent per environment, so a sandbox can mirror your production setup: the same product names, feature names, and even user emails can exist in each environment without conflict.
Account-level settings are shared across the whole account and can be changed only from the production environment: team members, roles, SSO settings, sending domains, billing, and sandbox environment management itself.
## Creating a sandbox
Go to the [`Settings -> Sandbox Environments`](https://app.cryptlex.com/settings/sandboxes) page in the admin portal and click **`Create`**. The number of sandbox environments included depends on your plan.
To switch between environments, use the environment switcher in the top-right corner of the admin portal. All pages then show the selected environment's data.
Deleting a sandbox permanently deletes everything inside it. The production environment cannot be deleted.
## Testing your app against a sandbox
The `Product.dat` file identifies the environment it was downloaded from. To point your app at a sandbox, switch to the sandbox, create a product there, and use that product's `Product.dat` and product ID in your app. LexActivator and LexFloatClient then work against the sandbox automatically; no code changes or special configuration are needed. License keys, users, and trials from the sandbox behave exactly as they would in production.
To use the Web API against a sandbox, create a [personal access token](https://cryptlex.com/docs/integrations-and-automation/personal-access-tokens) while working inside the sandbox; access tokens are scoped to the environment they were created in.
[Webhooks](https://cryptlex.com/docs/integrations-and-automation/webhooks) and [automated emails](https://cryptlex.com/docs/integrations-and-automation/automated-emails) are also configured per environment, so you can test your event-driven flows end to end without touching production integrations or emailing real customers.
The customer portal and SSO logins always serve the production environment. Named user licenses can still be tested in a sandbox through the SDK's user authentication flow.
## Restricting team members to a sandbox
Team members with the admin or super admin role have access to all environments. On plans that include custom roles, you can restrict a team member with a custom role to specific environments by selecting them in the **Environments** field when inviting or editing the team member. This lets you, for example, confine a developer or an external contractor to a sandbox, keeping production data out of reach.
## Sandbox limits
Sandboxes have small, fixed resource limits that do not depend on your plan; they are meant for testing, not production workloads. Your usage against these limits is shown on the sandbox's overview page. Activations in a sandbox never trigger plan upgrades. If your testing needs higher limits, contact us through the [contact page](https://cryptlex.com/contact).
## Going to production
When your integration is ready to ship:
1. Recreate your configuration (products, license templates, features, webhooks) in the production environment. Names are independent per environment, so you can reuse the same names.
2. Replace the sandbox `Product.dat` in your app with the one from your production product, and use the production product's ID.
3. Use production personal access tokens in your server-side automation.
Then walk through the [Launch Checklist](https://cryptlex.com/docs/getting-started/launch-checklist) before shipping to real customers.
---
# Best Practices
Section: SDKs and APIs
URL: https://cryptlex.com/docs/sdks-and-apis/best-practices
Summary: Best practices for integrating Cryptlex SDKs into your app, covering permission flags, offline-first license verification, server sync, license states, floating license hygiene, and deployment.
Last updated: 2026-09-15
These recommendations apply to any app integrating [LexActivator](https://cryptlex.com/docs/sdks-and-apis/lexactivator) or [LexFloatClient](https://cryptlex.com/docs/sdks-and-apis/lexfloatclient), regardless of language or platform.
## Choose the right permission flag
The flag you pass to `SetProductId()` determines where LexActivator stores activation data:
- **`LA_USER`** is the default for regular desktop apps running with user privileges.
- **`LA_ALL_USERS`** shares a single activation across all OS users (system-wide activation). It is supported on Windows and macOS. On Linux, achieve the same result by pointing LexActivator at a system-wide directory with `SetDataDirectory()` and passing this flag.
- **`LA_IN_MEMORY`** keeps all data in memory instead of on disk. Use it when your app has no write access to the disk, and for [hosted floating licenses](https://cryptlex.com/docs/licensing-models/floating-licenses/hosted-floating-licenses) with a per-instance leasing strategy. Note that the license must be activated again every time the app restarts.
For where each flag stores the data on each OS, and for environments where the default location is not writable, see [activation data storage](https://cryptlex.com/docs/sdks-and-apis/lexactivator#activation-data-storage).
## Verify locally, sync in the background
Every time your app starts, verify the license locally by checking the cryptographic signature of the stored activation with `IsLicenseGenuine()`. This works offline and adds no startup latency. The SDK then periodically syncs with the Cryptlex servers in a separate background thread, picking up server-side changes such as renewals, suspension, or revocation. See [server sync](https://cryptlex.com/docs/sdks-and-apis/lexactivator#server-sync) for exactly when each kind of change reaches the client and how to receive it through the license callback.
Configure a sensible [server sync interval](https://cryptlex.com/docs/license-management/license-templates#server-sync-interval) in your license template. If frequent syncing is not required, use 3600 seconds or greater, or one day (86400 seconds) to avoid generating a high volume of API requests.
## Handle every license state
Do not treat license verification as a boolean. Your app should branch on the status codes and respond appropriately:
- **`LA_OK`**: the license is valid.
- **`LA_EXPIRED`**: the license has expired; prompt for renewal.
- **`LA_SUSPENDED`**: the license was [suspended](https://cryptlex.com/docs/license-management/suspending-and-revoking-licenses) server-side, for example for a failed payment; access is typically restored without reactivation.
- **`LA_GRACE_PERIOD_OVER`**: the SDK could not reach the Cryptlex servers for longer than the [server sync grace period](https://cryptlex.com/docs/license-management/license-templates#server-sync-grace-period) configured in the license template. Decide deliberately whether to block usage or degrade gracefully.
- **`LA_FAIL`**: the license is not activated or was [revoked](https://cryptlex.com/docs/license-management/suspending-and-revoking-licenses); require a fresh activation.
Whenever `IsLicenseGenuine()`, `ActivateLicense()`, or any other LexActivator function returns anything other than `LA_OK`, log the exact status code it returned, along with the timestamp. A message like "license check failed" is not enough; the numeric code pins down the cause, such as a clock tamper, a fingerprint mismatch, or a permission error, and is the first thing the Cryptlex team asks for when troubleshooting an integration. When the code is `LA_FAIL`, also log the value of `GetLastActivationError()`, which tells you why the activation data was cleared.
## Activate on user action, not on every start
Call `ActivateLicense()` (or `ActivateTrial()`) once, ideally on a button click, when the user enters their key. Executing activation on every start unnecessarily contacts the Cryptlex servers; after activation, startup checks should rely on the local verification described above.
## Release floating licenses promptly
For floating licenses, call `DeactivateLicense()` (LexActivator) or `DropFloatingLicense()` (LexFloatClient) when the user exits the app. Otherwise the seat stays leased and becomes a [zombie license](https://cryptlex.com/docs/licensing-models/floating-licenses/overview#zombie-licenses), unavailable to other users until the lease expires.
With LexFloatClient, the license lease renews itself automatically in a background thread, and your renewal callback is invoked **from that background thread**. Do not interact with UI elements directly from the callback; marshal back to the main thread using your framework's mechanism. If the renewal fails, request a new license from the callback.
## Support restricted environments
- Customers behind corporate proxies usually need nothing: LexActivator detects system proxy settings automatically, and you can offer manual configuration via `SetNetworkProxy()`. Restrictive firewalls need [whitelisting](https://cryptlex.com/docs/sdks-and-apis/proxies-and-firewall).
- For air-gapped machines, support [offline activations](https://cryptlex.com/docs/licensing-models/offline-licenses), or deploy [LexFloatServer](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/overview) inside the customer's network.
## Ship the runtime dependencies
On older Windows versions (Windows 7, 8, Windows Server 2008/2012), the SDKs require the Microsoft Visual C++ 2015 (or later) runtime. Include the required DLLs with your installer, or install the latest [Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist).
## Before you ship
Walk through the [Launch Checklist](https://cryptlex.com/docs/getting-started/launch-checklist) to verify your licensing model, test the failure paths, and secure your credentials.
---
# Overview
Section: License Management
URL: https://cryptlex.com/docs/license-management/overview
Summary: Manage the full license lifecycle in Cryptlex, from templates and creation to subscriptions, metadata, usage metering, suspension, revocation, and maintenance policies.
Last updated: 2026-08-07
Once you have [chosen a licensing model](https://cryptlex.com/docs/licensing-models/choosing-a-licensing-model), this section covers the day-to-day operations of running your licensing, including creating licenses for customers, keeping subscriptions current, and controlling access over each license's lifetime.
## The license lifecycle
1. **Define your defaults** with a [license template](https://cryptlex.com/docs/license-management/license-templates). Every license inherits its configuration, such as type, activations, subscription interval, and security settings, from a template, so you set these values once.
2. **Create licenses** for your customers through the admin portal or the Web API, typically as part of your [order automation](https://cryptlex.com/docs/integrations-and-automation/custom-integration).
3. **Keep subscriptions current.** For time-based licenses, configure the subscription interval and renew licenses on payment. See [Subscription Licensing](https://cryptlex.com/docs/licensing-models/subscription-licensing).
4. **Attach your own data** to licenses, users, and activations with [metadata](https://cryptlex.com/docs/license-management/metadata), and track consumption with [meter attributes](https://cryptlex.com/docs/license-management/meter-attributes) for usage-based models.
5. **Control access** when something changes. Temporarily block or permanently invalidate a license with [suspension and revocation](https://cryptlex.com/docs/license-management/suspending-and-revoking-licenses).
6. **Govern updates** by linking a [maintenance policy](https://cryptlex.com/docs/licensing-models/software-maintenance-and-support) that defines how long, and for which versions, the customer receives software updates.
To find out when a license, an activation, or a user was last active, see [Activity Timestamps](https://cryptlex.com/docs/license-management/activity-timestamps).
---
# License Templates
Section: License Management
URL: https://cryptlex.com/docs/license-management/license-templates
Summary: Cryptlex license templates define default license properties and support advanced configurations for subscriptions, floating licenses, activations, security, and restrictions.
Last updated: 2026-09-15
A license template acts as a blueprint for the licenses you create for your customers. Before you start creating licenses, you need to create a license template that contains the default values for the license fields.
While creating a license from any license template, you can override all the properties of the license template. The license template provides you with default values for all the properties of a license, so you don't have to provide them every time you create a new license.
You can edit a license template at any time, but the changes only apply to licenses created after the edit. Licenses already created from the template are not affected.
## Creating a license template
Go to the [License Templates](https://app.cryptlex.com/license-management/license-templates) page in the admin portal and click **`Create`**. A license template form with the following fields opens:
### Name
The name of the license template.
### Type
There are three types of licenses:
- **Node-locked:** The default type, which locks the license to the machine.
- **Hosted floating:** Used for creating a hosted floating license.
- **On-premise floating:** Used for creating an on-premise floating license.
### Subscription Interval
To define a recurring subscription, use the `subscriptionInterval` property to specify the interval and the `subscriptionStartTrigger` to determine when that duration begins. To learn more, refer to [Subscription Licensing](https://cryptlex.com/docs/licensing-models/subscription-licensing).
### Lease Duration
This option is valid for **hosted-floating** and **on-premise-floating** license types only. It sets the duration for which your app can lease the floating license from the license server.
To enable lease auto-renewal for the **hosted-floating** license type, keep the **server sync interval at least 30 seconds shorter than the lease duration**. To allow an unlimited lease duration, set this property to 0 or -1.
For the **on-premise floating** license type, lease duration can be set to `0` to honor the lease duration set in the **LexFloatServer** config file.
### Leasing strategy
This option is valid for **hosted-floating** and **on-premise-floating** license types only. It allows for the following strategies:
- **Per-Machine:** Each machine will only consume a single floating license/activation, irrespective of the number of instances (processes) of your app being run on the machine.
- **Per-Instance:** Each instance (process) of your app will consume a separate floating license/activation, irrespective of whether the instances are running on the same machine or different machines. The [fingerprint matching strategy](#fingerprint-matching-strategy) is ignored for per-instance leases.
For the **hosted-floating** license type, if you want to use a **per-instance** leasing strategy, ensure that the permission flag in the **LexActivator** `SetProductId()` function is set to `LA_IN_MEMORY`.
### Allowed floating clients
This option is valid for the **on-premise floating** license type only. It sets the maximum number of concurrent clients that can lease the floating license from the LexFloatServer.
For hosted floating licenses, the maximum number of concurrent clients that can lease the license from the server is determined by the `allowedActivations` property.
### Allowed activations
Allowed number of activations (seats) for the license. What an activation represents depends on the license type:
- **Node-locked:** the number of devices the license can be activated on. For example, if you allow 10 activations, the license can be used on 10 different machines at the same time.
- **Hosted floating:** the number of activations (seats) that can be leased concurrently from the Cryptlex server.
- **On-premise floating:** the number of LexFloatServer instances that the license allows.
To allow unlimited activations, set this property to 0 or -1.
### Allowed deactivations
Allowed number of deactivations for the license. This setting is ignored for **hosted-floating** licenses.
To allow unlimited deactivations, set this property to -1. The default value for hosted floating licenses is -1, indicating unlimited deactivations.
### Server sync interval
Whenever the application starts (and `IsLicenseGenuine()` is called the first time), the server sync occurs immediately in a separate thread. This setting determines the interval for further server syncs until the application is closed or license is deactivated. For what server sync does and when server-side changes reach activated machines, see [server sync](https://cryptlex.com/docs/sdks-and-apis/lexactivator#server-sync).
The server sync interval can be set as low as 180s. If frequent syncing is required, we recommend 3600s or greater; otherwise, set it to one day (86400s) to avoid generating a high volume of API requests.
### Server sync grace period
The duration for which the server sync failure due to a network error is acceptable.
To allow an infinite grace period, for example for a fully offline or air-gapped environment, set this property to -1. Otherwise, set it to a finite value such as `2592000` (30 days), which requires the machine to reconnect and sync with the server at least once within that period.
### Allowed clock offset
The allowed difference between the network time and the system time. This can be used to allow license activations on machines where system clocks run behind the network time.
Set this property to -1 to disable clock validation in LexActivator. This is only configurable for node-locked perpetual licenses.
### Fingerprint matching strategy
LexActivator generates a structured fingerprint of the machine which allows for multiple fingerprint matching strategies. It allows for the following strategies:
- Exact: This strategy requires an exact match of all the hardware components used to generate the fingerprint. If there is a minor change in the hardware, the fingerprint will not be accepted, and the machine will be treated as a different machine.
- Fuzzy: This strategy uses fuzzy matching by comparing different hardware fingerprints and if the comparison score is greater than a minimum threshold value, the machine is accepted. This is the **recommended** strategy.
- Loose: This strategy is similar to fuzzy but with a much lower threshold value.
Some machines report major changes in their hardware fingerprints due to hardware or driver issues. In such cases, change the strategy to **Loose**.
### Required metadata keys
List of required metadata keys that a license using the license template must have.
### Required meter attributes
List of required meter attributes which a license using the license template must have.
### Expiring soon event offset
The number of seconds to wait before the license expiration date to trigger the `license.expiring-soon` webhook event.
### Key pattern
Regex for the license key format. The default regex is `^([A-F0-9]{6}-){5}[A-F0-9]{6}$`, which generates license keys in the format `XXXXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX`.
You can also set a custom key when creating a license via the Web API by passing the `key` field, for example `NODE-LOCKED-XXXXXX-...`, `HOSTED-FLOATING-XXXXXX-...`, or `NODE-LOCKED-OFFLINE-XXXXXX-...`, so your app can infer the license type from the key before activation.
### Allowed countries
List of the allowed countries. The country name is resolved using the IP address. If none of the countries is selected, then all the countries are allowed.
### Disallowed countries
List of the disallowed countries. The country name is resolved using the IP address. If none of the countries is selected, this setting is ignored. If a country is set in both Allowed and Disallowed, Disallowed is given preference.
### Allowed IP range
IP address range in CIDR notation, for example `196.210.135.105/24`. If no range is specified, then all the IP addresses are allowed.
### Allowed IP addresses
List of the allowed IP addresses. If none of the IP addresses is included, then all the IP addresses are allowed.
### Disallowed IP addresses
List of the disallowed IP addresses. If none of the IP addresses is included, this setting is ignored.
### Allow VM Activations
Whether to allow an activation inside a virtual machine. Cloned virtual machines may report the same fingerprint.
### Allow Container Activations
Whether to allow an activation inside a container. This must never be set to `true` for an **on-premise floating** license.
### Crypto binding
When the `cryptoBindingEnabled` property is set to `true`, activations are bound cryptographically instead of relying on the device fingerprint. This makes it a reliable way to license apps running inside containers or virtual machines, provided the app has an active internet connection. Crypto binding is supported on Windows and Linux. To learn more, refer to [Containers and Virtual Machines](https://cryptlex.com/docs/licensing-models/containers-and-virtual-machines).
### Allow Client Lease Duration
Whether to allow the client app to set the lease duration for the hosted floating license activation.
### User locked
Prevents multiple users on the same OS from sharing the same activation. If enabled, each user consumes a license activation from the allowed number of activations for the license.
### Disable geolocation
If you don't want to store the IP address and location of the license activation, set this property to `true`.
---
# Metadata
Section: License Management
URL: https://cryptlex.com/docs/license-management/metadata
Summary: Cryptlex metadata lets you add custom fields to products, licenses, users, and activations, enabling flexible data storage, visibility control, and schema enforcement.
Last updated: 2026-09-14
Metadata lets you attach custom fields to products, licenses, users, and activations.
To enable, disable, or configure features of your app per license, use [feature entitlements](https://cryptlex.com/docs/features-and-entitlements/overview) instead of metadata. Entitlements are purpose-built for feature gating, while metadata is meant for storing auxiliary data such as order references.
## Metadata properties
Metadata added to a product, license, or user has three properties:
Property
Description
Key
Name of the metadata field.
Value
Value stored against the key.
View Permissions
Controls who can see the field. See below.
### View Permissions
Admins control the visibility of metadata by granting one or more of the following permissions:
Permission
Visible to
Web API
Activation
Your app, through the LexActivator SDK
`POST /v3/activations`
User
End users in the customer portal
`GET /v3/me/licenses`
Organization
Organization admins in the customer portal
`GET /v3/organizations/:id/licenses`
Reseller
Reseller admins in the reseller portal
`GET /v3/resellers/:id/licenses`
## Product metadata
This metadata can be added to products and can be accessed in your application once a trial or license is activated.
Use it to store product-level information that you want to access in your app and that can change over time. Retrieve it in your app with **`GetProductMetadata()`**.
## License metadata
License metadata allows you to attach custom data to each license at the time of creation. You can store useful identifiers such as `order_id`, `customer_id`, or any other key-value data relevant to your business logic.
This metadata can also be accessed within your application once the license is activated, making it ideal for use cases where additional context is needed alongside the license. Retrieve it in your app with **`GetLicenseMetadata()`**.
Each license can have up to 10 metadata fields.
To require licenses to have specific metadata properties, set them in the license template's `requiredMetadataKeys` field. License metadata is available only after the license has been successfully activated. If you need to access metadata prior to activation, consider implementing a [named user licensing](https://cryptlex.com/docs/licensing-models/named-user-licenses/overview) workflow. In this approach, **`GetUserLicenses()`** would retrieve a list of user license objects along with the license metadata.
## Enforcing a schema for metadata fields
You can enforce the schema for metadata fields in the license template, too, so you don't have to manually create the fields every time you create a license. Provide the field names as comma-separated strings, such as `order_id` and `customer_id`, in the required metadata keys property of the license template.
## User metadata
This metadata can be added to your license users at the time of creating a user. You can store additional data like `phone_number` and `address` in the user metadata. Retrieve it in your app with **`GetLicenseUserMetadata()`**.
## Activation metadata
This metadata can be added by your application at the time of activating the license.
It can be used to collect additional details from the machine on which the license is activated, such as the number of CPU cores or custom data provided by the user. Set it with **`SetActivationMetadata()`** and retrieve it with **`GetActivationMetadata()`**.
## Trial activation metadata
This metadata can be added by your application at the time of activating the trial.
It can be used to collect additional details from the machine on which the trial is activated, such as the number of CPU cores or custom data provided by the user. Set it with **`SetTrialActivationMetadata()`** and retrieve it with **`GetTrialActivationMetadata()`**.
---
# Meter Attributes
Section: License Management
URL: https://cryptlex.com/docs/license-management/meter-attributes
Summary: Cryptlex meter attributes let you track and enforce feature or usage limits in licenses, with configurable properties, permissions, and SDK support.
Last updated: 2026-07-13
Meter attributes let you track and enforce usage limits on a license, which is useful when you want your customers to pay for what they actively use regardless of how long they possess your product. Usage can be defined as the number of specific operations performed in your app, the number of times it is run, or the number of times a feature is used.
## Meter attribute properties
A meter attribute added to a license has the following properties:
Property
Description
Name
Name of the meter attribute.
Allowed Uses
The maximum allowed uses for the attribute. Set to -1 to allow unlimited uses.
Total Uses
The current uses for the attribute. Its value can be incremented, decremented, or reset in your app using LexActivator functions.
Gross Uses
Tracks the lifetime usage of the meter attribute.
Floating
If set to `true`, the uses consumed by an activation are automatically reset when the activation is deleted.
View Permissions
Controls who can see the attribute. See below.
### View Permissions
Admins control the visibility of meter attributes by granting one or more of the following permissions:
Permission
Visible to
Web API
Activation
Your app, through the LexActivator SDK
`POST /v3/activations`
User
End users in the customer portal
`GET /v3/me/licenses`
Organization
Organization admins in the customer portal
`GET /v3/organizations/:id/licenses`
Reseller
Reseller admins in the reseller portal
`GET /v3/resellers/:id/licenses`
## Enforcing meter attributes schema
To make some meter attributes required for your licenses, add them to the `requiredMeterAttributes` property of the license template. This also automatically creates the meter attributes in the license form.
## Using meter attributes
For the end-to-end flow and pricing patterns, see [Usage-Based Licensing](https://cryptlex.com/docs/licensing-models/usage-based-licensing). This section covers the mechanics.
The functions your app uses to report usage depend on the license type.
### Node-locked and hosted floating licenses
Report usage through these LexActivator functions:
**`GetActivationMeterAttributeUses()`**, **`IncrementActivationMeterAttributeUses()`**, **`DecrementActivationMeterAttributeUses()`**, **`ResetActivationMeterAttributeUses()`**
Each increment, decrement, or reset is a real-time network call to the Cryptlex server, so the count is always current. To meter while offline, buffer the counts locally in your app and apply them in bulk with a single increment once the connection is restored.
### On-premise floating licenses
Report usage through the corresponding LexFloatClient functions:
**`GetFloatingClientMeterAttributeUses()`**, **`IncrementFloatingClientMeterAttributeUses()`**, **`DecrementFloatingClientMeterAttributeUses()`**, **`ResetFloatingClientMeterAttributeUses()`**
These calls go to your LexFloatServer, which tracks usage locally, making metering possible in offline and air-gapped environments.
### Usage limits
For all license types, usage aggregates across every activation into one shared pool, and the license stays genuine even at the limit. When the count reaches the `allowedUses` limit, further increments fail with a limit-reached error: **`LA_E_METER_ATTRIBUTE_USES_LIMIT_REACHED`** from LexActivator, or **`LF_E_METER_ATTRIBUTE_USES_LIMIT_REACHED`** from LexFloatClient.
---
# Suspending and Revoking Licenses
Section: License Management
URL: https://cryptlex.com/docs/license-management/suspending-and-revoking-licenses
Summary: Suspend a license to temporarily block access without losing activation data, or revoke it to permanently invalidate it, using the Cryptlex license update endpoint.
Last updated: 2026-08-07
Cryptlex gives you two server-side ways to invalidate a license. **Suspension** is temporary, meaning access is restored automatically when you allow the license again. **Revocation** is permanent, meaning the local license data is invalidated and the user must reactivate if you ever allow the license again.
Both actions reach your customer's app only at its next successful [server sync](https://cryptlex.com/docs/license-management/license-templates#server-sync-interval). Until then the app keeps running on the license data it already holds, and a machine with no connectivity, such as an [offline](https://cryptlex.com/docs/licensing-models/offline-licenses) or air-gapped deployment, never receives the change at all.
## Suspending vs revoking
Suspending
Revoking
`IsLicenseGenuine()` returns
`LA_SUSPENDED`
`LA_FAIL`
Local license data
Remains intact
Invalidated and removed
Reactivation attempt
Not needed
`ActivateLicense()` returns `LA_E_REVOKED`
Restoring access
Allow the license; `IsLicenseGenuine()` returns `LA_OK` automatically after first sync
Allow the license; the user must reactivate
## When to suspend
Suspending a license is appropriate when you expect the license to become valid again without requiring user action. Typical scenarios include:
- Temporary payment issues, such as a failed renewal or an invoice pending payment
- Short-term policy or usage violations that can be resolved
- Temporarily blocking access while an issue is being reviewed or investigated
- Grace period handling for subscriptions
In these cases, the license data remains intact on the client machine. Once the license is allowed on the server side, the application automatically returns to a valid state without requiring a reactivation.
## When to revoke
Revoking a license is appropriate when the license should no longer be trusted and must be invalidated completely. Typical scenarios include:
- Refunds or chargebacks where the entitlement is permanently removed
- Cancellation scenarios where the existing activation must be invalidated
When a license is revoked, the client removes the local license data. If the license is later allowed again or replaced, the user must perform a fresh activation.
## Suspending or revoking via the Web API
Both actions are done through the [license update endpoint](https://cryptlex.com/reference/web-api/patch-licenses-id): set the `suspended` or `revoked` property to `true`, or back to `false` to allow the license again.
You can also perform both actions from the admin portal, using the **`Actions`** menu next to the license on the `Licenses` page.
---
# Activity Timestamps
Section: License Management
URL: https://cryptlex.com/docs/license-management/activity-timestamps
Summary: How Cryptlex records the last activity on a license, an activation, and a user, and when to use lastUsedAt, lastSyncedAt, lastSeenAt, or lastLoginAt.
Last updated: 2026-08-25
Cryptlex records when a license, an activation, or a user was last active. These four timestamps live on three different entities and are updated by different events, so pick the one that matches the question you are answering. All of them are shown on the corresponding pages in the admin portal and returned on the entity in the Web API.
Timestamp
Entity
Updated when
`lastUsedAt`
License
Any activation of the license is created, updated, or successfully synced
`lastSyncedAt`
Activation
That specific activation successfully syncs with the Cryptlex servers
`lastSeenAt`
User
An activation linked to the user successfully syncs
`lastLoginAt`
User
The user logs in to the customer portal
Three of these four timestamps advance only when a client reaches the Cryptlex servers, so they stay unchanged on machines that are [offline](https://cryptlex.com/docs/licensing-models/offline-licenses) or air-gapped. On those deployments, no recent activity does not mean the license is unused.
## lastUsedAt
`lastUsedAt` is maintained at the license level and represents the most recent activity across all activations associated with the license. It is updated whenever an activation is created, updated, or successfully synchronized with the Cryptlex servers. For a license with multiple activations, the value reflects the most recent activity among all of them, so it tells you whether the license is in use at all, not which machine used it.
## lastSyncedAt
`lastSyncedAt` is maintained at the activation level and indicates when that specific activation last successfully synchronized with the Cryptlex servers. Unlike `lastUsedAt`, which aggregates activity across a license, `lastSyncedAt` reflects the synchronization status of an individual activation, which makes it the field to check when you are diagnosing a single machine.
## lastSeenAt
`lastSeenAt` is maintained at the user level and indicates the most recent time a user was observed using an application associated with their account. It is updated when a license activation linked to the user successfully synchronizes with the Cryptlex servers, which makes it useful for tracking recent end-user activity across your licensed applications.
## lastLoginAt
`lastLoginAt` is maintained at the user level and indicates the most recent time the user successfully logged in to the [customer portal](https://cryptlex.com/docs/customers/customer-portal). It is updated on successful portal authentication, so you can use it to track customer portal access.
`lastLoginAt` tracks customer portal logins, whereas `lastSeenAt` tracks application usage that results in a successful server sync from a license activation linked to the user. A user who runs your app but never opens the portal has a recent `lastSeenAt` and no `lastLoginAt` at all.
## Timezones
Cryptlex stores every timestamp in UTC. This applies to the activity timestamps on this page as well as to dates such as `expiresAt` on licenses and feature entitlements. The Web API returns timestamps in UTC, and the SDKs return them as Unix timestamps, which are always UTC based.
The admin portal, however, displays every timestamp converted to the local timezone of the browser you are viewing it in. The conversion also applies when you set a date: picking an expiration date in the admin portal sets it to 11:59:59 PM on that date in your own local timezone, and the stored UTC value can therefore fall on the next calendar day in UTC.
When your app compares a timestamp such as `expiresAt` against the current time, always compare in UTC. Never localize the stored value to the machine's timezone first, because the machine's timezone has no relation to the timezone in which the date was set.
---
# Overview
Section: Features and Entitlements
URL: https://cryptlex.com/docs/features-and-entitlements/overview
Summary: Cryptlex feature entitlements define product capabilities and access, managed via Entitlement Sets or licenses, enabling flexible tiers, limits, and feature-based control.
Last updated: 2026-07-13
Feature entitlements let you control which capabilities of your product each license enables. With them you can sell consistent product tiers such as Standard, Pro, and Enterprise, roll out features to selected customers, and set per-license values and limits for your application to enforce, all from the same build of your app. This is often called feature-based licensing.
## How entitlements are assigned
Feature entitlements can be assigned in two ways, which you can also combine:
- Through **Entitlement Sets**, which group multiple feature entitlements into reusable collections for standardized license tiers. See [Features and Entitlement Sets](https://cryptlex.com/docs/features-and-entitlements/features-and-entitlement-sets).
- **Directly on individual licenses** for more granular, per-customer control, including overriding values from a linked Entitlement Set. See [Assigning Feature Entitlements](https://cryptlex.com/docs/features-and-entitlements/license-feature-entitlements).
## Values and expiry
Each feature entitlement may optionally include a value, always a string, which your application interprets, for example as a number or a flag, to enforce limits or enable conditional functionality. Feature entitlements enable, disable, and configure features; they do not track consumption. To meter usage per license, such as API calls or exports, use [meter attributes](https://cryptlex.com/docs/license-management/meter-attributes), which implement usage-based (metered) licensing.
When a feature entitlement is added directly to a license or a value is overridden at the license level, it can also include an expiration date. This expiry date is license specific and applies only to that custom or overridden entitlement, enabling time-bound access to individual features, such as feature-level trials or temporary feature unlocks.
## Using entitlements in your app
Your application retrieves entitlements at runtime through LexActivator or LexFloatClient and adapts its behavior accordingly. See [Accessing Feature Entitlements](https://cryptlex.com/docs/features-and-entitlements/accessing-feature-entitlements), and browse the [Use Cases](https://cryptlex.com/docs/features-and-entitlements/use-cases) for practical patterns like tiering, value-based limits, beta rollouts, and feature trials.
---
# Features and Entitlement Sets
Section: Features and Entitlements
URL: https://cryptlex.com/docs/features-and-entitlements/features-and-entitlement-sets
Summary: Define your product's features and group them into Entitlement Sets to model license tiers like Basic, Pro, and Enterprise.
Last updated: 2026-08-07
Features define the licensable capabilities of your product, and Entitlement Sets group them into reusable bundles that model license tiers such as Basic, Pro, and Enterprise.
## Features
Features in Cryptlex represent capabilities or functionalities within your product that can be licensed. If a feature is present in an Entitlement Set or directly assigned to a license, it is considered enabled for that license. Any value associated with a feature is an optional string intended for your application logic to interpret, for example as a number or a flag.
To create a feature, navigate to the [`Entitlements -> Features`](https://app.cryptlex.com/entitlements/features) page in the admin portal.
## Entitlement Sets
Entitlement Sets are reusable collections of features grouped together to represent a package or product tier, such as Standard, Pro, or Enterprise. You can create an Entitlement Set that encapsulates a bundle of feature entitlements and apply it to multiple products and licenses.
Each feature entitlement within an Entitlement Set can optionally include a string value, which your application logic can interpret to apply constraints or offer conditional access.
To create an Entitlement Set, navigate to the [`Entitlements -> Entitlement Sets`](https://app.cryptlex.com/entitlements/entitlement-sets) page in the admin portal. You can add multiple feature entitlements to an Entitlement Set and set a value for each feature. To link Entitlement Sets or individual feature entitlements to licenses, see [Assigning Feature Entitlements](https://cryptlex.com/docs/features-and-entitlements/license-feature-entitlements).
---
# Assigning Feature Entitlements
Section: Features and Entitlements
URL: https://cryptlex.com/docs/features-and-entitlements/license-feature-entitlements
Summary: Cryptlex feature entitlements can be assigned via Entitlement Sets for tiered licensing, directly on licenses for custom needs, or combined for flexible overrides.
Last updated: 2026-08-07
Feature entitlements define what a license enables within your product. In Cryptlex, feature entitlements can be assigned to a license in two ways: via Entitlement Sets or directly on the license itself. This flexibility allows both standardized tier-based licensing and custom per-customer overrides.
A feature is available to a license by being present on it and unavailable when absent, so there is no enabled or disabled value to set. The value is a separate, optional string field that Cryptlex delivers, so your app parses and interprets it, and your code enforces whatever it configures.
Entitlement changes are not instant. After you link an Entitlement Set, override a value, or add a feature, your customer's app keeps reading the entitlements it already holds until its next [server sync](https://cryptlex.com/docs/license-management/license-templates#server-sync-interval) completes.
## Linking feature entitlements via Entitlement Sets
Entitlement Sets serve as reusable bundles of feature entitlements that can be linked to multiple licenses. You can select an Entitlement Set when creating or editing a license in the admin portal.
**Use when:**
* You offer predefined product tiers like "Standard", "Pro", or "Enterprise"
* You want to ensure consistency across licenses
* You prefer centralized management of feature entitlements
## Assigning feature entitlements directly to a license
Feature entitlements can also be added directly to a license without using an Entitlement Set, when creating or editing the license in the admin portal.
**Use when:**
* Each customer requires a specific configuration outside the standard tiers
* You need to override a value from the Entitlement Set for a specific license
* You want to grant temporary or experimental access to a feature
## Combining both approaches
Cryptlex supports a hybrid approach where a license can use both an Entitlement Set and additional direct license-level feature entitlements.
**Example:**
* License uses the `Pro` Entitlement Set (with feature entitlement `max_projects = 20`)
* You override `max_projects = 50` directly on the license
* You also add `priority_support` directly for this specific customer
At runtime, license-level entitlements take precedence over values from the linked Entitlement Set. See [Accessing Feature Entitlements](https://cryptlex.com/docs/features-and-entitlements/accessing-feature-entitlements) for the resolution order.
---
# Accessing Feature Entitlements
Section: Features and Entitlements
URL: https://cryptlex.com/docs/features-and-entitlements/accessing-feature-entitlements
Summary: Retrieve feature entitlements at runtime with the SDKs to enforce license-based feature access in your app.
Last updated: 2026-08-09
Use the Cryptlex SDK, either LexActivator or LexFloatClient, to retrieve feature entitlements at runtime and apply licensing logic in your application. These entitlements determine which features should be enabled, disabled, or configured dynamically based on the active license.
You can retrieve entitlements:
* Individually, by specifying a feature name.
* As a complete list, for broader entitlement evaluation.
A license-level feature entitlement can carry an expiry date, and the SDK exposes that date as `expiresAt` so your app can decide what happens once it passes: disable the feature, drop it to a restricted mode, or fall back to `baseValue`. When a license-level entitlement overrides the value from the linked Entitlement Set, `baseValue` holds that original value, so your app can revert to it. Cryptlex does not enforce the date for you, so nothing changes until your app acts on it. See [Feature trials](https://cryptlex.com/docs/features-and-entitlements/use-cases#feature-trials).
## Retrieving a specific feature entitlement
Call **`GetFeatureEntitlement()`** in LexActivator, or **`GetHostFeatureEntitlement()`** in LexFloatClient, passing the feature name. The function returns the entitlement associated with the specified feature name. Internally, the resolution process follows this order:
1. **License-level entitlement:** If the feature entitlement is directly defined on the license, its value is returned.
2. **Entitlement Set:** If not found at the license level, the function checks whether the license is linked to an Entitlement Set and returns the feature entitlement from there, if present.
This allows for flexible and hierarchical entitlement management, where licenses can override defaults defined in Entitlement Sets when necessary. See [Assigning Feature Entitlements](https://cryptlex.com/docs/features-and-entitlements/license-feature-entitlements) for how these overrides are configured.
## Retrieving all feature entitlements
Call **`GetFeatureEntitlements()`** in LexActivator, or **`GetHostFeatureEntitlements()`** in LexFloatClient. The function returns all feature entitlements associated with the license. Use it when you need to evaluate multiple entitlements at once or when dynamically configuring application behavior based on the full set of features included in the license.
---
# Use Cases
Section: Features and Entitlements
URL: https://cryptlex.com/docs/features-and-entitlements/use-cases
Summary: Common ways to use feature entitlements, from product tiering and usage limits to controlled rollouts and per-customer customization.
Last updated: 2026-07-13
The following use cases demonstrate how Entitlement Sets and license-level feature entitlements in Cryptlex can be used to define product behavior, manage license tiers, and enforce custom limits.
## Product tiering
Organizations often offer multiple editions of their product, such as Standard, Pro, and Enterprise, with different capabilities. Entitlement Sets help group relevant feature entitlements into reusable tiers.
**For example:**
Tier
Feature Entitlements
Standard
`basic_export`
Pro
`basic_export`, `analytics_dashboard`
Enterprise
`basic_export`, `analytics_dashboard`, `priority_support`, `team_sharing`
Licenses are linked to the relevant Entitlement Set, and the application logic checks which features are enabled to control access.
## Value-based limits
Feature values can be used to define fixed limits, such as the maximum number of projects or team members, which your application enforces at runtime.
**Example:**
* Feature: `max_team_members`
* Value: `5`, `20`, or `unlimited`
* Usage: The application reads the value at runtime and enforces the limit accordingly.
This approach enables per-license limits without requiring new builds or manual configuration. Note that feature entitlements do not track consumption; to meter actual usage against a quota, such as API calls or exports consumed, use [meter attributes](https://cryptlex.com/docs/license-management/meter-attributes).
## Controlled feature rollouts (beta access)
Entitlements can be used to enable or disable features for a specific group of users, such as beta testers.
**Example:**
* Features: `beta_dark_mode`, `ai_autocomplete`
* Added only to selected licenses
* Application checks for feature presence before enabling UI or functionality
This allows safe, controlled rollouts without the need for separate builds.
## Feature trials
Expiry dates on license-level feature entitlements can be used to grant temporary access to specific features without affecting the rest of the license. This is useful for offering feature trials, promotional unlocks, or time-limited access to any premium functionality within your app.
**Example:**
* Feature: `advanced_reporting`
* Expiry date: `2026-12-31`
* Usage: The expiry information is exposed through the SDK via the **`GetFeatureEntitlement()`** and **`GetFeatureEntitlements()`** functions (see [Accessing Feature Entitlements](https://cryptlex.com/docs/features-and-entitlements/accessing-feature-entitlements)) and must be evaluated and enforced by the application itself.
This approach allows targeted, time-bound feature access without creating separate license types or Entitlement Sets and without requiring license reissuance.
---
# Overview
Section: Customers
URL: https://cryptlex.com/docs/customers/overview
Summary: Understand how Cryptlex models your customers as users, organizations, and resellers, how a license binds to each, and which portal every role uses.
Last updated: 2026-07-25
Cryptlex models the people and companies you sell to with three entities: users, organizations, and resellers. How you bind a license depends on who your customer is: bind it to a user for an individual, to an organization to share one license across multiple users in a company, or allot licenses to a reseller who sells on your behalf. You can still license anonymously with just license keys, but creating these entities unlocks self-service portals, named user licensing, and delegated license management.
## Users
A **user** represents a single end customer. A user can be as simple as a contact linked to a license, but users can also log in to the customer portal to view and manage their licenses, and are required for the named user licensing model. See [Users](https://cryptlex.com/docs/customers/users).
## Organizations
An **organization** groups users who belong to the same company, and it is how you link a single license to multiple users. You assign the license to the organization, and its admin distributes access through user groups from the customer portal. This lets you sell to a company rather than a single user, while the organization admin manages license distribution. See [Organizations](https://cryptlex.com/docs/customers/organizations).
## Resellers
A **reseller** represents a sales partner who sells your software. You allot licenses to the reseller, and its admin manages the licenses, users, and organizations under the account from a dedicated reseller portal. See [Resellers](https://cryptlex.com/docs/customers/resellers).
## Portal access by role
Role
Portal
What they manage
user
[Customer portal](https://cryptlex.com/docs/customers/customer-portal)
Their own licenses, activations, and downloads
organization-admin
[Customer portal](https://cryptlex.com/docs/customers/customer-portal)
The organization's users, groups, and licenses
reseller-admin
[Reseller portal](https://cryptlex.com/docs/customers/resellers)
Licenses, users, and organizations under the reseller account
All of them can log in with email and password or through your identity provider. See [SSO](https://cryptlex.com/docs/sso/overview).
---
# Users
Section: Customers
URL: https://cryptlex.com/docs/customers/users
Summary: Create and manage users in Cryptlex, assign them roles, and link them to licenses so customers can access the customer portal.
Last updated: 2026-08-07
In Cryptlex, a user represents your end customer. A user can be as simple as a contact (a name and email) linked to a license, or the actual licensee, as in the [named user licensing model](https://cryptlex.com/docs/licensing-models/named-user-licenses/overview), where the license is tied to the user's identity.
To link a single license to multiple users, use an [organization](https://cryptlex.com/docs/customers/organizations) instead. The organization admin can then delegate that license to its users.
Creating a user is not required for standard licensing workflows, but it is required for access to the [customer portal](https://cryptlex.com/docs/customers/customer-portal). A user linked to one or more licenses can independently view their licenses and related details, download published releases, view activations, perform deactivations, and complete offline activations. This self-service reduces your support workload.
The named user licensing model requires a user, and the license must be linked to that user.
## User roles
A user's role determines what they can do in the [customer portal](https://cryptlex.com/docs/customers/customer-portal) and how they relate to your other customers.
- **User** (`user`) is your end customer. They can view their licenses, activations, and releases for the products they are licensed for.
- **Organization admin** (`organization-admin`) manages an [organization](https://cryptlex.com/docs/customers/organizations). They can set up user profiles, form user groups, and allocate the organization's licenses to its members.
- **Reseller admin** (`reseller-admin`) manages a [reseller](https://cryptlex.com/docs/customers/resellers) account. They can view and manage all licenses, users, and organizations under their reseller account, and assign licenses as needed.
## Creating a user
1. Go to the [`Customers -> Users`](https://app.cryptlex.com/customers/users) page in the admin portal and click **`Create`**.
2. Provide the required details, including First Name, Last Name, Email, Password, and Role.
A user can be created with one of three roles: `user`, `organization-admin`, or `reseller-admin`. During creation, you can also associate an end user with an organization or a reseller through the Organization or Reseller field.
## Linking a user to a license
1. Go to the [`Licenses`](https://app.cryptlex.com/license-management/licenses) page in the admin portal.
2. Click **`Create`** to create a new license, or edit an existing license.
3. Open the `Customer` tab and link the user.
You can also create, link, and authenticate users programmatically using the [Web API](https://cryptlex.com/reference/web-api).
## Tracking user activity
A user carries two separate activity timestamps: `lastSeenAt` for application usage and `lastLoginAt` for customer portal logins. See [Activity Timestamps](https://cryptlex.com/docs/license-management/activity-timestamps) for what updates each one.
---
# Organizations
Section: Customers
URL: https://cryptlex.com/docs/customers/organizations
Summary: Cryptlex organizations group users under a company with organization-admins managing end-users, user-groups, licenses, and activations.
Last updated: 2026-07-13
An **organization** groups users who belong to the same company, and it is how you link a single license to multiple users. You assign the license to the organization, and its admin (a user with the `organization-admin` role) distributes access through user groups from the [customer portal](https://cryptlex.com/docs/customers/customer-portal). This lets you sell to a company rather than a single user, while the organization admin manages license distribution instead.
## Creating an organization
1. Go to the [`Customers -> Organizations`](https://app.cryptlex.com/customers/organizations) page in the admin portal.
2. Click **`Create`** and provide the organization's details.
The `Allowed Users` property caps how many users the organization admin can create, which lets you sell a fixed number of seats.
## Creating an organization admin
1. Go to the [`Customers -> Users`](https://app.cryptlex.com/customers/users) page in the admin portal and click **`Create`**.
2. In the Role field, select `organization-admin`.
3. In the Organization field, select the organization to link to this admin.
For details on user roles, see [Users](https://cryptlex.com/docs/customers/users).
## Linking a license to an organization
1. Go to the [`Licenses`](https://app.cryptlex.com/license-management/licenses) page in the admin portal.
2. Click **`Create`** to create a new license, or edit an existing license.
3. Open the `Customer` tab and link the organization.
For everything an organization admin can do, see [role-based access](https://cryptlex.com/docs/customers/customer-portal#organization-admins) in the customer portal documentation.
---
# Customer Portal
Section: Customers
URL: https://cryptlex.com/docs/customers/customer-portal
Summary: The Cryptlex customer portal lets users and organization admins manage licenses and activations, download releases, and perform offline activations.
Last updated: 2026-08-25
Your customers can log in to the customer portal to:
* View their licenses and details, including total activations, deactivations, allowed activations and deactivations, subscription status, and license status.
* Perform offline activations and deactivations.
* Download published releases of your app.
* View and update their profile details, such as first name, last name, email, and password.
The customer portal is served at `https://.customer.cryptlex.com`. You can find your exact customer portal URL, and configure a custom domain for it, on the [`Settings -> Customizations`](https://app.cryptlex.com/settings/customizations) page in the admin portal.
Offline trial activations can't be handled in the customer portal because the portal requires logging in, and trial users don't have accounts. To automate offline trial activations, host this form on GitHub or your own server: [https://github.com/cryptlex/offline-trial-activation-form](https://github.com/cryptlex/offline-trial-activation-form)
## Role-based access
The customer portal presents one of two views depending on the customer's role.
### Organization admins
Users with the `organization-admin` role get an enhanced view where they can manage the whole organization. They can:
* View all licenses associated with the organization.
* Create and manage the organization's users and user groups.
* Link user groups to specific licenses.
* Configure [SAML SSO](https://cryptlex.com/docs/sso/saml-sso) for the organization's users.
See [Organizations](https://cryptlex.com/docs/customers/organizations).
### Users
Users with the `user` role see only the licenses tied to them: licenses linked directly to their account, and, within an organization, the licenses linked to their user groups.
## Customizing the customer portal
You can change the customer portal logo and set up a custom domain on the [`Settings -> Customizations`](https://app.cryptlex.com/settings/customizations) page in the admin portal.
## Need more features?
If you need more features in the customer portal, we'll be glad to add them. Contact us through the [contact page](https://cryptlex.com/contact).
---
# Resellers
Section: Customers
URL: https://cryptlex.com/docs/customers/resellers
Summary: Invite resellers to sell your software through a dedicated reseller portal where they manage customers and assign licenses, while you monitor and limit their activity.
Last updated: 2026-08-25
Resellers let you bring your sales partners, distributors, and sales channels into Cryptlex so they can sell your software. Reseller admins log in to a dedicated reseller portal to manage their customers and licenses, where they can:
* Create, edit, and delete users and organizations.
* Assign and revoke their allotted licenses for those users and organizations.
* Renew licenses or update license expiration dates.
* Track activations across their customers.
* Perform offline activations and deactivations for their customers.
Their end users can also perform offline activations and deactivations from the customer portal.
The Resellers feature is currently in beta. Expect ongoing enhancements as we refine the experience. Please share your feedback through the [contact page](https://cryptlex.com/contact).
## Creating a reseller
1. Go to the [`Customers -> Resellers`](https://app.cryptlex.com/customers/resellers) page in the admin portal.
2. Click **`Create`** and provide the reseller's details.
## Creating a reseller admin
1. Go to the [`Customers -> Users`](https://app.cryptlex.com/customers/users) page in the admin portal and click **`Create`**.
2. In the Role field, select `reseller-admin`.
3. In the Reseller field, select the reseller to link to this admin.
This user can then log in to the reseller portal to manage the reseller account.
The reseller portal is served at `https://.reseller.cryptlex.com`. You can find your exact reseller portal URL on the [`Settings -> Customizations`](https://app.cryptlex.com/settings/customizations) page in the admin portal.
## Linking licenses to a reseller
Because resellers cannot create licenses themselves, you create the licenses upfront and allot them to a dedicated reseller.
1. Go to the [`Licenses`](https://app.cryptlex.com/license-management/licenses) page in the admin portal.
2. Click **`Create`** to create a new license, or edit an existing license. You can also create licenses in bulk.
3. Open the `Customer` tab and link the reseller.
The reseller admin can then distribute the linked licenses to their own users and organizations from the reseller portal, but cannot generate new ones.
## Renewing licenses from the reseller portal
Reseller admins can keep their customers' licenses active without going through you. From the reseller portal, they can:
* Renew a license, which adds the current subscription interval to the expiration date and starts another cycle.
* Update the expiration date of a license to extend, shorten, or correct when it expires.
Both actions work the same way as they do in the admin portal. For details on how renewals and expiration dates behave, see [subscription licensing](https://cryptlex.com/docs/licensing-models/subscription-licensing).
A reseller admin can renew a license or update its expiration date only if the `reseller-admin` role allows it. See [Configuring reseller permissions](#configuring-reseller-permissions) below.
## Configuring reseller permissions
Reseller permissions are configurable, so you decide exactly what reseller admins can do in the reseller portal. Go to the [`Settings -> Roles`](https://app.cryptlex.com/settings/roles) page in the admin portal and edit the `reseller-admin` role to define its permissions.
For example, you can let reseller admins create users and organizations but not delete them, or allow license renewals while blocking expiration date updates.
Permissions are set on the role, so a change applies to every user assigned the `reseller-admin` role.
## Managing your resellers
You can limit reseller activity using the `Allowed Users` and `Allowed Organizations` properties on the reseller, and track reseller activity using filters and the audit logs.
## Customizing the reseller portal
You can change the reseller portal logo and set up a custom domain on the [`Settings -> Customizations`](https://app.cryptlex.com/settings/customizations) page in the admin portal.
## Need more features?
If you need more features in the reseller portal, contact us through the [contact page](https://cryptlex.com/contact).
---
# Overview
Section: Releases
URL: https://cryptlex.com/docs/releases/overview
Summary: Cryptlex releases let you host and distribute your software securely to licensed users and deliver automatic updates, with downloads gated by license keys or access tokens.
Last updated: 2026-08-06
Cryptlex lets you distribute your software applications securely to licensed users, protecting your software from unlicensed distribution. You host your release files on our servers (bandwidth is free, even if you distribute a million copies), and Cryptlex gates every download of these hosted files behind a valid license key or access token. You can also add external files hosted on your own server, whose URLs Cryptlex passes through as-is without gating.
Using Cryptlex releases is optional. If you already ship updates through your own mechanism, you can keep it, and [maintenance policies](https://cryptlex.com/docs/licensing-models/software-maintenance-and-support) still work independently of release hosting. What you give up is download gating behind a valid license and the built-in update check.
## How releases work
A release represents one version of your product. Each release has:
- **Version**, dot-separated digits in one of three forms: `$MAJOR.$MINOR`, `$MAJOR.$MINOR.$PATCH`, or `$MAJOR.$MINOR.$PATCH.$BUILD` (for example, `1.2`, `1.2.3`, or `1.2.3.4`), used for ordering releases and detecting updates.
- **Platforms**, such as `windows`, `macos`, or `linux`, so each operating system gets the right files. You create the platforms you need; none exist by default.
- **Channel**, such as `stable` or `beta`, so you can ship pre-release versions to a subset of users. Only `stable` exists by default; create any others you need.
- **Files**, either uploaded to Cryptlex hosting or added as external files hosted on your own server.
## Release lifecycle
1. **Create** the release and upload its files. See [Creating Releases](https://cryptlex.com/docs/releases/creating-releases).
2. **Publish** it to freeze it; published releases are read-only and become visible to your users.
3. **Archive** it when you want to retire it; archived releases disappear from the customer portal and update checks, though previously shared direct download URLs keep working.
## Secure delivery
Download URLs for hosted release files require the customer's license key or an access token, so only licensed users can download your software. Customers can download releases from the [customer portal](https://cryptlex.com/docs/customers/customer-portal), or your website can fetch them through the Web API. See [Distributing Releases](https://cryptlex.com/docs/releases/distributing-releases).
## Automatic updates
Your app can check whether a newer release is available, using either the Web API or the LexActivator `CheckReleaseUpdate()` function, and then download and install it. See [Auto-Updates](https://cryptlex.com/docs/releases/auto-updates).
---
# Creating Releases
Section: Releases
URL: https://cryptlex.com/docs/releases/creating-releases
Summary: Cryptlex releases let you manage and distribute software versions securely, with support for uploads, external hosting, channels, notes, and publishing controls.
Last updated: 2026-07-13
Whenever you release a new version of your software, create a new release in the Cryptlex admin portal (or through the Web API). After you create the release, upload your software bundle with the release, or host the software bundle on your own server.
## Creating a release
To create a release through the admin portal, go to the `Releases` section in the sidebar and click the **`Add`** button. A create release form with the following fields pops up:
Field
Description
Name
A friendly name to identify the release, such as `MyApp v1.2`.
Version
Dot-separated digits in one of three forms: `$MAJOR.$MINOR`, `$MAJOR.$MINOR.$PATCH`, or `$MAJOR.$MINOR.$PATCH.$BUILD` (for example, `1.2`, `1.2.3`, or `1.2.3.4`).
Platforms
Such as `windows`, `macos`, or `linux`, so each operating system gets the right files. You create the platforms you need; none exist by default.
Channel
Such as `stable` or `beta`, so you can ship pre-release versions to a subset of users. Only `stable` exists by default; create any others you need.
Notes
The release notes, which support [Markdown](https://www.markdownguide.org/basic-syntax).
## Uploading release files
In the create release form, upload the release files that you want to distribute securely to your licensed users.
You can also upload a release file using any command-line HTTP client like `curl`:
For accounts in the EU data region, use `releases.eu.cryptlex.com` as the hostname.
If you are using self-hosted Cryptlex, upload to your own releases hostname instead:
The access token must have at least the following two permissions: `release:read`, `release:write`.
The file name in the upload URL must only contain letters, numbers, and the special characters `.` (period), `-` (hyphen), and `_` (underscore).
## Adding an external release file
Instead of uploading release files to Cryptlex, you can add release files hosted on your own server.
To add an external release file, click the **`Add External File`** option in the actions menu. Enter the details of your external release file in the form and click the **`Add File`** button. After that, the entry appears in the `Files` column of the table.
## Publishing a release
Once all the changes have been finalized, click the **`Publish`** button to freeze the release. After a release is published it becomes read-only.
## Archiving a release
Archiving a release allows you to hide a published release from end users without deleting it. Archived releases will no longer appear in the customer portal or in SDK update checks.
To archive a release:
1. Go to the [`Releases`](https://app.cryptlex.com/release-management/releases) page in the admin portal and locate the release you want to archive.
2. From the actions menu for that release, click **`Archive`**.
Archiving a release is permanent; it cannot be unarchived. However, if customers already know the exact release URL, they can still download it directly.
Once your release is published, see [Distributing Releases](https://cryptlex.com/docs/releases/distributing-releases) to deliver it to your customers and [Auto-Updates](https://cryptlex.com/docs/releases/auto-updates) to notify your app when a newer version is available.
---
# Distributing Releases
Section: Releases
URL: https://cryptlex.com/docs/releases/distributing-releases
Summary: Cryptlex secures release downloads behind license keys or access tokens, and lets you fetch the latest release download URLs of your product through the Web API.
Last updated: 2026-08-19
Release files hosted on Cryptlex are gated behind the customer's license. To download a file, the request must include either the customer's license key or an access token of a user associated with the license.
## Downloading a release
To download a release, the request must contain the license key as the **`key`** query parameter or an access token in the `Authorization` header.
### Download file using license key
### Download file using access token
The license key must belong to the product for which the release was created and the access token must belong to any user who is associated with the license of the product.
The external release files are not secured and hence don't require the **`key`** query parameter for download.
For accounts in the EU data region, use the `releases.eu.cryptlex.com` and `api.eu.cryptlex.com` hostnames instead.
## Downloading the latest release
To get the download URLs for the latest release of your product, invoke the [`/v3/releases/latest`](https://cryptlex.com/reference/web-api/get-releases-latest) endpoint.
#### Query parameters
Name
Type
Description
productId*
string
Unique identifier for the product
platform*
string
Release platform
channel
string
Release channel (defaults to "stable")
key*
string
License key
accountId*
string
Unique identifier for the account
It returns a **`200`** success response containing the download URLs of the latest release:
## Tracking release downloads
Every download of a Cryptlex-hosted release file is recorded as a release download event, capturing the release version and channel, the file, the user and license that downloaded it, the download status, and the location it was downloaded from. Use these events to track the rollout and adoption of new versions.
You can view release download events on the [`Release Management -> Release Download Events`](https://app.cryptlex.com/release-management/release-download-events) page in the admin portal, query them with the [`GET /v3/release-download-events`](https://cryptlex.com/reference/web-api/get-release-download-events) endpoint, or export them as a CSV file with the [`GET /v3/release-download-events/export`](https://cryptlex.com/reference/web-api/get-release-download-events-export) endpoint.
## Delivering updates
To detect from inside your app whether a newer release is available and deliver it automatically, see [Auto-Updates](https://cryptlex.com/docs/releases/auto-updates).
---
# Auto-Updates
Section: Releases
URL: https://cryptlex.com/docs/releases/auto-updates
Summary: Implement auto-updates in your app by checking for newer releases with the Cryptlex Web API or LexActivator's CheckReleaseUpdate function.
Last updated: 2026-09-14
Your app can detect whether a newer release is available for your product and prompt the user to update, or download the update silently. You can implement the check using either the Web API or LexActivator.
## Checking for updates using the Web API
Invoke the [/v3/releases/update](https://cryptlex.com/reference/web-api/get-releases-update) endpoint to check whether a new release is available by comparing it with the provided release version.
For accounts in the EU data region, use `https://api.eu.cryptlex.com` as the Web API base URL.
#### Query parameters
Name
Type
Description
productId*
string
Unique identifier for the product
platform*
string
Release platform
channel
string
Release channel (defaults to "stable")
version*
string
Current release version
key*
string
License key
accountId*
string
Unique identifier for the account
If an update is available it returns a **`200`** success response containing the release details along with the download URLs of its files (the same response shape as the [latest release endpoint](https://cryptlex.com/docs/releases/distributing-releases)), otherwise it returns a **`204`** empty response.
The `key` parameter is required unless the request carries an access token or a release download token, so the endpoint can verify that the requester is entitled to the release. To check for updates where no customer license key or token is available, such as from your own backend service or while your app runs in trial mode, create a dedicated dummy license for the product and use its key for the check. The dummy license does not need to be activated, and you can hard-code its key in your app or service.
## Checking for updates using LexActivator
LexActivator provides the **`CheckReleaseUpdate()`** function, which performs the same check and invokes your callback with the result. Sample code for all supported languages is available in the LexActivator sample projects on GitHub. The following sample code demonstrates it for C/C++.
notes);
break;
case LA_RELEASE_UPDATE_AVAILABLE_NOT_ALLOWED:
printf("A new update is available for the app but it's not allowed.");
printf("Release notes: %s", release->notes);
break;
case LA_RELEASE_UPDATE_NOT_AVAILABLE:
printf("Current version is already latest.");
break;
default:
printf("Error code: %d", status);
}
}
int main()
{
int status;
// init code - SetProductId(), SetProductData()
// Ensure that platform, channel and version actually exist for the release
status = SetReleasePlatform("windows");
if (LA_OK != status)
{
// handle error
}
status = SetReleaseChannel("stable");
if (LA_OK != status)
{
// handle error
}
status = SetReleaseVersion("1.2.3.4");
if (LA_OK != status)
{
// handle error
}
status = CheckReleaseUpdate(SoftwareReleaseUpdateCallback, LA_RELEASES_ALL, NULL);
if (LA_OK != status)
{
printf("Error checking for software release update: %d", status);
}
}`} />
## Ignoring PATCH and BUILD updates
The version format syntax in Cryptlex is **`$MAJOR.$MINOR.$PATCH.$BUILD`**. If you want to ignore **`$PATCH`** and **`$BUILD`** releases in the update API endpoint, you can pass a partial version.
The following table summarizes the expected response from the `/v3/releases/update` API endpoint when it is invoked with the **`version`** query parameter set to the values in the first column:
Version (Query Param)
Latest Version
Response (Status Code)
1.2.3.5
1.2.3.5
204
1.2.3.4
1.2.3.5
200
1.2.3
1.2.3.4
204
1.2
1.2.3.4
204
For example, if your latest release version is **`1.2.3.4`** and you invoke the update API endpoint with the **`version`** query parameter set to **`1.2.3`**, it returns a **`204`** status code indicating no update.
---
# Personal Access Tokens
Section: Integrations and Automation
URL: https://cryptlex.com/docs/integrations-and-automation/personal-access-tokens
Summary: Cryptlex personal access tokens provide scoped, time-bound, revocable API authentication for automation, CI/CD pipelines, and integrations.
Last updated: 2026-08-19
## What personal access tokens are
Personal access tokens allow you to authenticate Web API requests without using your account credentials. These tokens are scoped, revocable, and can be given an expiry, offering a secure way to interact with Cryptlex programmatically.
## Use cases
* Automating license and release management via the Web API
* Integrating with CI/CD pipelines
* Connecting third-party tools or internal scripts to Cryptlex
## Creating an access token
1. Go to the [`Developer -> Access Tokens`](https://app.cryptlex.com/developer/access-tokens) page from the sidebar in the admin portal.
2. Click the **`Create`** button.
3. In the popup:
- Enter a name for the token.
- Set an expiration date. Leave it blank to create a token that never expires.
- Assign [permissions](#permissions-overview) by selecting the required scopes (Read or Write access) for each module, such as Activations, Releases, and Licenses.
4. Click **`Create`**.
5. On the next screen, copy the access token and store it securely. For security, Cryptlex does not keep a retrievable copy, so it cannot be shown again. If you lose it, [rotate the existing token](#token-lifetime-and-rotation) to generate a new one.
## Using an access token
Pass the token in the `Authorization` header as a Bearer token with every Web API request. The base URL is `https://api.cryptlex.com`; if your account is in the EU region, use `https://api.eu.cryptlex.com` instead.
## Token lifetime and rotation
Set an expiration date whenever you can. A blank expiry creates a token that never expires, so use non-expiring tokens only for long-lived automation.
To rotate a token, use the **`Rotate`** action on the [`Developer -> Access Tokens`](https://app.cryptlex.com/developer/access-tokens) page. This generates a new value while keeping the token's name and permissions; copy the new value (same one-time visibility rule as above) and update your application or integration. Rotate periodically, and immediately if a token is exposed or leaked.
Revoke any token you no longer need from the `Developer -> Access Tokens` page.
## Permissions overview
Each token can be customized with fine-grained permissions:
* **Read**: allows retrieving data, such as listing licenses or fetching release details.
* **Write**: allows performing actions, such as creating licenses or updating releases.
---
# Webhooks
Section: Integrations and Automation
URL: https://cryptlex.com/docs/integrations-and-automation/webhooks
Summary: Set up Cryptlex webhooks to get real-time notifications for license, trial, and subscription events, verify signed payloads, and automate your workflows.
Last updated: 2026-09-14
Webhooks notify your systems about events in your Cryptlex account in real time. When a subscribed event occurs, such as a license being created or activated, Cryptlex sends an HTTP POST request with a signed JSON payload describing the event to an endpoint you specify.
## When to use webhooks
Webhooks are the building block for automating communication between Cryptlex and your other systems asynchronously. You might use webhooks to:
* Email a license key to your customer after a successful purchase.
* Email your customer when the license expires.
* Get notified through email or chat apps like Slack when a user activates a trial or license.
* Any other integration your business needs.
## Creating a webhook
To create a webhook, go to the `Developer -> Webhooks` section in the admin portal and click the **`Add`** button. A webhook form with the following fields will pop up:
#### Name
Name for the webhook.
#### URL
The endpoint which will receive the HTTP POST payload.
#### Token
The token is a secret that will be used to sign the payload using the **HMAC SHA-256** algorithm.
#### Events
The list of events which trigger the POST request.
#### Enabled
If unchecked, the webhook will be disabled and will not send a POST request on the defined events.
## Which event fires for which action
Some actions fire a dedicated event instead of the generic `updated` event, so subscribe to the specific events for the actions you care about:
* **Activating a license** fires `license.first-activated` on the first activation; it does not fire `license.updated`.
* **Changing when a license expires** fires different events depending on the action: renewing fires `license.renewed`, and setting the expiration date directly through the [`PATCH /v3/licenses/{id}/expires-at`](https://cryptlex.com/reference/web-api/patch-licenses-id-expires-at) endpoint, typical for subscription renewals, fires `license.expiresAt.updated`. Subscribe to both if you track expiry changes.
* **Cascaded deletions do not fire `deleted` events for child entities.** Deleting a license deletes its activations silently, without firing `activation.deleted` for each one; only `license.deleted` fires. The same applies to every parent-child relationship, such as a product and its licenses, releases, and trial activations, or a release and its files. Users and licenses are siblings, not parent and child, so deleting a user does not delete their licenses; it clears the `user` property on them instead.
## Webhook payload
Each event type has a specific payload format with relevant event information. The payload is JSON, encoded as UTF-8, and is signed with the **HMAC SHA-256** algorithm; the signature is included in the `webhook-signature` header. HTTP header names are case-insensitive, so read the header without expecting a specific casing. A typical delivery has the following structure:
`id` uniquely identifies the event for the webhook and does not change between delivery attempts, so use it as an idempotency key to discard an event you have already processed. `triggeredAt` is the time the event was triggered and also stays the same across retries, so a retried delivery carries the same body and signature as the original attempt.
## Verifying the signature
Verify the signature on every delivery to make sure the request really came from Cryptlex. The signature is computed as:
Follow these rules, which cover the most common integration bugs:
* **Hash the raw request body exactly as received, before parsing it.** Parsing the JSON and re-serializing it will not reproduce the original bytes, because key order and whitespace are not preserved. This is the single most common mistake.
* **Treat the body as UTF-8 bytes.** The payload is not ASCII-escaped, so values with accented characters or emoji carry raw multi-byte UTF-8. Hash the bytes as received; do not decode them to a string in another encoding and re-encode.
* **Use a constant-time comparison** to compare the computed signature with the header value, not string equality.
* **Read the `webhook-signature` header case-insensitively.**
Node.js
Python
bool:
digest = hmac.new(token.encode("utf-8"), raw_body, hashlib.sha256).digest()
expected = base64.b64encode(digest).decode("ascii")
return hmac.compare_digest(signature_header or "", expected)`} />
## Testing a webhook
You can send a test delivery to your endpoint at any time using the **`Test`** action in the actions menu on the [`Developer -> Webhooks`](https://app.cryptlex.com/developer/webhooks) page in the admin portal.
The test sends a sample payload for an event of your choice (it defaults to the webhook's first subscribed event), signed exactly like a real delivery. The test result includes your endpoint's response along with the exact body that was signed and the signature that was sent, so you can reproduce the signature computation while debugging.
Two properties of test deliveries are worth knowing:
* They are not recorded as webhook event logs and never affect the webhook's health or suspension.
* The sample payload carries representative but synthetic values, including non-ASCII characters, so an endpoint that verifies signatures incorrectly fails the test instead of passing it by accident.
## Delivery and retries
* Each delivery attempt times out after 15 seconds. A delivery fails on any non-2xx response, or when no response is received.
* A failed event is retried up to 5 attempts in total, 5 minutes apart. An event that exhausts all attempts is marked **failed**.
## Webhook event logs
Webhook event logs show information about POST requests that were made when the webhook was triggered. You can view them on the [`Developer -> Webhook Event Logs`](https://app.cryptlex.com/developer/webhook-event-logs) page in the admin portal, and use them to see the status code returned by your endpoint, when the request was sent and received, and the reason for any retry. You can also resend a delivery using the **`Resend`** action in the actions menu of an event log.
An event log has one of the following statuses: **queued**, **pending**, **retrying**, **succeeded**, **failed**, or **cancelled**. The **cancelled** status means the webhook was disabled or suspended at the time the event fired, so no delivery was attempted.
## Webhook health
The **status** property reflects the operational state of a webhook:
* A webhook starts as **Healthy**. A single failed attempt does not change the status; the event simply enters its retry cycle.
* The status transitions to **Unhealthy** once an event has exhausted all of its retry attempts and been marked **failed**.
* The status transitions from **Unhealthy** to **Suspended** when the 50 most recent completed events have all failed. When a webhook is suspended, Cryptlex emails your account's notification address.
* While **Suspended**, no automatic delivery attempts are made, but events are still logged, so they can be resent later.
* A successful delivery, including a manual resend, immediately restores the webhook status back to **Healthy**.
---
# Automated Emails
Section: Integrations and Automation
URL: https://cryptlex.com/docs/integrations-and-automation/automated-emails
Summary: Send automated emails to customers on license and user events, with custom templates, verified sending domains, and delivery tracking.
Last updated: 2026-09-14
Automated emails send an email to your customers when a specific event occurs in Cryptlex. The following events are supported:
- `license.created`
- `license.renewed`
- `license.expiring-soon`
- `license.expired`
- `license.deleted`
- `license.subscription.updated`
- `license.expiresAt.updated`
- `license.key.rotated`
- `license.maintenance-expired`
- `license.maintenance-expiring-soon`
- `user.created`
- `user.reset-password-request`
- `organization.user.created`
- `reseller.user.created`
Use [webhooks](https://cryptlex.com/docs/integrations-and-automation/webhooks) instead of automated emails if you have a complex workflow.
The password reset link sent in these emails contains a reset token that is valid for **48 hours**. A customer who opens the link after it expires must request a fresh one.
## Creating an automated email
To create an automated email, go to the `Developer -> Automated Emails` section in the admin portal and click the **`Add`** button. An automated email form with the following fields will pop up:
After creating the automated email, make sure you link it with the product.
#### Name
Name of the automated email.
#### From Name
The from name that should appear for the email.
#### From Email
The email address to be used for sending the email.
The from email address will only be used if you have verified your domain, otherwise, it will default to **noreply@cryptlex-mail.com**. Each From Email address used in automated emails must be individually verified from the [`Settings -> Customizations -> Manage From Emails`](https://app.cryptlex.com/settings/customizations) page in the admin portal. No-reply addresses on a verified domain are the exception and do not require individual verification. Once any other email address is verified, it can be used as a From Email. You may verify and use multiple email addresses as needed.
#### Subject
The subject of the email. This can contain data placeholders too.
#### ReplyTo
The reply-to address for the email. We recommend setting this to your support email.
#### Body
The body of the email. You can use HTML for formatting.
#### Event
The event to trigger the email.
#### Enabled
If unchecked, the automated email will be disabled and no email will be sent on the defined event.
#### Custom
By default, your email body will be automatically wrapped in a responsive HTML email. In case you want to prevent that and use your own branded email, this property can be set to `true`.
## Data placeholders
All the properties of [user](https://cryptlex.com/reference/web-api/get-users-id), [license](https://cryptlex.com/reference/web-api/get-licenses-id) and [product](https://cryptlex.com/reference/web-api/get-products-id) resources can be accessed in the **body** and the **subject** of the automated email. The general syntax is **`resource.propertyName`**. The following is a sample automated email body:
Dear {user.firstName},
Thank you for ordering {product.displayName}.
Your license key for the {product.displayName} is:
{license.key}
You can use this license key to activate {product.displayName} on
{license.allowedActivations} device(s).
For any queries or issues you can contact us at
support@mycompany.com and we will assist you promptly.
Best Regards,
The MyCompany HelpDesk
`} />
## Data filters
Data filters can be used to format the date and number fields in automated emails.
### format_date
Formats date and times.
Input
Output
For more date format specifiers refer to the following: [https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings#table-of-format-specifiers](https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings#table-of-format-specifiers)
### format_number
Formats numbers.
Input
Output
For other supported filters please refer to the following: [https://shopify.github.io/liquid/filters/abs/](https://shopify.github.io/liquid/filters/abs/)
## Sending test emails
After you have created the automated email, click the **`Send Test Email`** option in the actions menu in the table. You can use this to test your automated email.
## Verifying email domain
For Cryptlex to send emails on your behalf using your **From Email** address, you must verify that you own the domain. This is done by adding a Sending Domain in Cryptlex and verifying the DNS records shown in the Sending Domain.
If you don't add the domain verification records, Cryptlex sends emails using the `noreply@cryptlex-mail.com` email address. If you want to give your customers a white-label experience, hiding all Cryptlex branding, you must add and verify the sending domain.
### To verify that a domain belongs to you
1. On the `Settings -> Customizations` page in the admin portal, click the **`Add`** button in the `Email Sending Domain` section to add your domain.
2. Verify the domain by adding the required TXT and CNAME DNS entries.
3. After you have added the CNAME and TXT records, click the **`Verify`** button to confirm that all of your records are now valid.
After your domain is verified, leave the CNAME and TXT records in place.
## Automated email event logs
Automated email event logs show information about the emails that were sent by an automated email. You can use automated email event logs to see the status of all the emails that were sent, the email body and even manually resend the email if needed.
---
# Stripe
Section: Integrations and Automation
URL: https://cryptlex.com/docs/integrations-and-automation/stripe
Summary: Integrate Stripe with Cryptlex to automate license creation, user management, and subscription renewals through secure webhook events.
Last updated: 2026-07-13
This guide walks you through integrating Stripe with Cryptlex to automate license creation and subscription renewals. The integration supports both one-time purchases and subscriptions.
## Prerequisites
1. Complete the Cryptlex [Quick Start Guide](https://cryptlex.com/docs/getting-started/quick-start) to set up your product and license templates.
2. Deploy the Stripe-Cryptlex integration script using one of the following options:
- **Self-hosted**: Follow our [deployment guide](https://github.com/cryptlex/third-party-integrations/tree/main/stripe) to run the integration on your infrastructure.
- **Cryptlex-hosted**: Let Cryptlex host the integration for a nominal fee. Contact us through the [contact page](https://cryptlex.com/contact) to request managed hosting.
## Step 1: Set up products in Stripe
In your Stripe Dashboard:
1. Navigate to `Products` and create your desired product(s).
2. Add the following metadata keys to the Stripe checkout session (both are required):
- `CRYPTLEX_PRODUCT_ID`
- `CRYPTLEX_LICENSE_TEMPLATE`
## Step 2: Configure webhooks
1. In your Stripe Dashboard, go to `Developers -> Webhooks`.
2. Click **`Add Endpoint`**, and enter the URL where your integration script is hosted.
3. Select the following events to listen for:
- `checkout.session.completed`: Triggers license creation after successful checkout.
- `invoice.paid`: Triggers license creation and also handles subscription renewals.
- `customer.created`: Creates the corresponding user in Cryptlex.
4. Retrieve the **signing secret** and provide it to your integration script for webhook verification.
## What happens next
Once the integration is active:
- New licenses are automatically created after successful Stripe payments.
- New users are created in Cryptlex using the customer's name and email from Stripe, and are automatically linked to the corresponding license.
- Licenses are automatically renewed in Cryptlex when the corresponding Stripe subscription renews.
Each license includes a metadata field named `stripe_subscription_id` that stores the Stripe subscription ID. Do not modify this value.
## Need more help?
If you need help with the Stripe integration, contact us through the [contact page](https://cryptlex.com/contact).
---
# Paddle
Section: Integrations and Automation
URL: https://cryptlex.com/docs/integrations-and-automation/paddle
Summary: Integrate Paddle with Cryptlex to automate software license creation, subscription renewals, suspensions, and revocations using Paddle webhooks.
Last updated: 2026-07-13
This guide walks you through integrating Paddle with Cryptlex for automated license management. The integration supports both one-time purchases and subscriptions. For subscriptions, it handles renewals, suspensions, and revocations based on the corresponding subscription events.
## Prerequisites
1. Complete the Cryptlex [Quick Start Guide](https://cryptlex.com/docs/getting-started/quick-start) to set up your product and license templates.
2. Deploy the Paddle-Cryptlex integration script using one of the following options:
- **Self-hosted**: Follow our [deployment guide](https://github.com/cryptlex/third-party-integrations/tree/main/paddle) to run the integration on your infrastructure.
- **Cryptlex-hosted**: Let Cryptlex host the integration for a nominal fee. Contact us through the [contact page](https://cryptlex.com/contact) to request managed hosting.
## Step 1: Set up products in Paddle
In your Paddle Dashboard:
1. Navigate to `Catalog -> Products` and click **`New Product`**. Follow the on-screen instructions to create your desired product(s).
2. Add the following custom attributes to your product:
- `cryptlex_license_template_id`
- `cryptlex_product_id`
## Step 2: Configure webhooks
1. In your Paddle Dashboard, go to `Developer Tools -> Notifications`.
2. Click **`New Destination`**, and enter the URL where your integration script is hosted.
Append `/v1` to the base URL when configuring a webhook.
3. Select the following events to listen for:
- `transaction.completed`: Triggers license creation after a successful checkout.
- `subscription.paused`: Triggers license suspension when a subscription is paused.
- `subscription.canceled`: Triggers license revocation when a subscription is canceled in Paddle.
- `customer.created`: Creates the corresponding user in Cryptlex.
4. Retrieve the **signing secret** and provide it to your integration script for webhook verification.
## What happens next
Once the integration is active:
- New licenses are automatically created after successful Paddle payments.
- New users are created in Cryptlex using the customer's name and email from Paddle, and are automatically linked to the corresponding license.
- Licenses are automatically renewed in Cryptlex when the corresponding Paddle subscription renews.
Each license includes a metadata field named `paddle_subscription_id` that stores the Paddle subscription ID. Do not modify this value.
## Need more help?
If you need help with the Paddle integration, contact us through the [contact page](https://cryptlex.com/contact).
---
# FastSpring
Section: Integrations and Automation
URL: https://cryptlex.com/docs/integrations-and-automation/fastspring
Summary: Set up FastSpring integration with Cryptlex to automate license creation, renewals, suspensions, and deletions for one-time purchases and subscriptions.
Last updated: 2026-07-13
This guide walks you through integrating FastSpring with Cryptlex for automated license management. The integration supports both one-time purchases and subscriptions. For subscriptions, it handles renewals, suspensions, and deletions based on the corresponding subscription events.
## Prerequisites
1. Complete the Cryptlex [Quick Start Guide](https://cryptlex.com/docs/getting-started/quick-start) to set up your product and license templates.
2. Deploy the FastSpring-Cryptlex integration script using one of the following options:
- **Self-hosted**: Follow our [deployment guide](https://github.com/cryptlex/third-party-integrations/tree/main/fastspring) to run the integration on your infrastructure.
- **Cryptlex-hosted**: Let Cryptlex host the integration for a nominal fee. Contact us through the [contact page](https://cryptlex.com/contact) to request managed hosting.
## Step 1: Set up products in FastSpring
1. Go to the `Catalog` section in FastSpring.
2. Add the following custom attributes to your product or subscription:
- `cryptlex_product_id`
- `cryptlex_license_template_id`
- `cryptlex_license_subscription_interval` (optional): overrides the subscription interval defined in the license template.
For multiple products, ensure each has unique custom attributes.
## Step 2: Configure webhooks
1. In FastSpring, go to `Developer Tools -> Webhooks`.
2. Click **`ADD WEBHOOK`** and enable webhook expansion.
3. Set the URL endpoint to the URL where your integration script is hosted.
4. Configure a secret in the HMAC SHA-256 Secret field and provide it to your integration script for webhook verification.
5. Configure the webhook to send specific or all available events, depending on your use case:
- `order.completed`: Creates a new license.
- `subscription.charge.completed`: [Renews](https://cryptlex.com/docs/licensing-models/subscription-licensing#renewing-a-subscription) the associated license.
- `subscription.payment.overdue`: [Suspends](https://cryptlex.com/docs/license-management/suspending-and-revoking-licenses) the associated license.
- `subscription.deactivated`: Deletes the associated license.
## What happens next
Once the integration is active:
- New licenses are automatically created after successful FastSpring payments.
- New users are created in Cryptlex using the customer's name and email from FastSpring, and are automatically linked to the corresponding license.
- Licenses are automatically renewed in Cryptlex when the corresponding FastSpring subscription renews.
Each license includes a metadata field named `fastspring_subscription_id` that stores the FastSpring subscription ID. Do not modify this value.
## Need more help?
If you need help with the FastSpring integration, contact us through the [contact page](https://cryptlex.com/contact).
---
# Zapier
Section: Integrations and Automation
URL: https://cryptlex.com/docs/integrations-and-automation/zapier
Summary: Connect Cryptlex with Zapier to automate license management, renewals, and notifications across thousands of apps like Gmail, Slack, and CRMs.
Last updated: 2026-07-13
[Zapier](https://zapier.com/) lets you connect Cryptlex with 5,000+ cloud apps, including Mailchimp, HubSpot, WooCommerce, and Shopify, and automate workflows without writing any server code. You can:
- Automatically send emails to your customers when you generate or renew a license key using Gmail, Mailgun or any other email service.
- Automatically generate licenses on successful payments.
- Automatically renew licenses when your customer renews the subscription.
- Get notified of each activation, license creation, and trial activation through email, Slack, or any other app.
- Integrate with your CRM, and more.
## Creating an access token for Zapier
To use Zapier to automate workflows, you need to create a [personal access token](https://cryptlex.com/docs/integrations-and-automation/personal-access-tokens) which Zapier will use for authorization while invoking the Cryptlex Web API.
To create an access token for Zapier, go to the [Personal Access Tokens](https://app.cryptlex.com/developer/access-tokens) section in the admin portal and create an access token with the following scope (permissions):
`activation:read`, `license:read`, `license:write`, `licenseTemplate:read`, `product:read`, `trialActivation:read`, `user:read`, `user:write`, `organization:read`, `organization:write`, `webhook:read`, `webhook:write`, `entitlementSet:read` (optional, required only if you want to link an Entitlement Set to a license)
To add metadata to a license, ensure the corresponding metadata key is first defined in the license template. To link an Entitlement Set to a license, ensure that the Entitlement Set has the product associated with it.
## Need more help?
If you need help with the Zapier integration, contact us through the [contact page](https://cryptlex.com/contact).
---
# Custom Integration
Section: Integrations and Automation
URL: https://cryptlex.com/docs/integrations-and-automation/custom-integration
Summary: Build your own payment integration with the Cryptlex Web API by creating a user and generating a license on successful payment, then delivering the license key by email.
Last updated: 2026-08-19
When the pre-built integrations do not fit your setup, you can build your own with the Cryptlex Web API and connect it to any payment processor, CRM, or third-party app. The most common case is automating order fulfillment: when a payment succeeds, your server creates a user and generates a license, then delivers the license key to your customer.
This guide shows the exact endpoints involved. For the complete request and response schema of each endpoint, including every optional field, see the [Web API reference](https://cryptlex.com/reference/web-api).
## How it works
1. Your payment processor calls your server endpoint (a webhook) on a successful payment.
2. Your server calls the Cryptlex Web API to create a user and a license.
3. Your server (or an automated email) delivers the license key to the customer.
## Authentication
All Web API requests are authenticated with a [personal access token](https://cryptlex.com/docs/integrations-and-automation/personal-access-tokens) sent in the `Authorization` header. Create the token in the admin portal and store it as a secret on your server, never in client code.
The base URL for all endpoints is `https://api.cryptlex.com`. If your account is in the EU region, use `https://api.eu.cryptlex.com` instead.
## Step 1: Create a user
Create a user from the customer details supplied by your payment processor. This is required if you want the customer to access the [customer portal](https://cryptlex.com/docs/customers/customer-portal), and mandatory for the named user licensing model.
The response contains the new user's `id`, which you use to link the license in the next step.
## Step 2: Generate a license
Create a license under your product. Pass a `licenseTemplateId` so the license inherits that template's configuration (subscription interval, activation limits, type, and so on), and set `userId` to link it to the user created above.
The response contains the generated license `key`, which is what your customer uses to activate your app.
You can find your `productId` and `licenseTemplateId` in the admin portal on the Products and License Templates pages. To create a license without linking a user, omit the `userId` field.
## Step 3: Deliver the license key
Send the license key to your customer using either of the following:
- Configure an [automated email](https://cryptlex.com/docs/integrations-and-automation/automated-emails) so Cryptlex emails the key on license creation.
- Use [webhooks](https://cryptlex.com/docs/integrations-and-automation/webhooks) to trigger your own mail script or a third-party service such as SendGrid or Mailgun.
## Custom development
Prefer to have it built for you? Our team can write the integration and automation scripts to connect Cryptlex with your payment processor, CRM, or other third-party apps. Send us the details through the [contact page](https://cryptlex.com/contact) and we will get it done in minimum time at a nominal cost.
## Need more help?
If you need help building your integration, contact us through the [contact page](https://cryptlex.com/contact).
---
# Overview
Section: SSO
URL: https://cryptlex.com/docs/sso/overview
Summary: Sign everyone in with your identity provider, from your team and customers in the portals to end users in your app through OIDC with LexActivator.
Last updated: 2026-07-13
Cryptlex has several login surfaces for different audiences. Understanding who logs in where makes the rest of this section easier to follow.
## Who logs in, and where
- **Your team** logs in to the [admin portal](https://app.cryptlex.com) to manage your account.
- **Your customers and organization admins** log in to the [customer portal](https://cryptlex.com/docs/customers/customer-portal) to view licenses and self-serve.
- **Resellers** log in to the reseller portal to manage their customers. See [Resellers](https://cryptlex.com/docs/customers/resellers).
- **End users inside your app** authenticate through the [Web API](https://cryptlex.com/docs/sdks-and-apis/licensing-via-web-api) or through OIDC with LexActivator, typically for [named user licensing](https://cryptlex.com/docs/licensing-models/named-user-licenses/overview).
## Supported identity providers
You can let all of the above log in with your existing identity provider instead of Cryptlex credentials. Cryptlex supports:
- [Google SSO](https://cryptlex.com/docs/sso/google-sso).
- [SAML SSO](https://cryptlex.com/docs/sso/saml-sso) with auto-provisioning and role mapping. Organization admins can also configure SAML SSO for their own organization, so their users log in to the customer portal with the organization's own identity provider.
- [OIDC SSO](https://cryptlex.com/docs/licensing-models/named-user-licenses/oidc-sso), which works with LexActivator for in-app user authentication.
---
# Google SSO
Section: SSO
URL: https://cryptlex.com/docs/sso/google-sso
Summary: Let your team, customers, and resellers log in to the Cryptlex portals with their Google accounts.
Last updated: 2026-07-13
With Google single sign-on (SSO), your team, customers, and resellers log in to the Cryptlex portals with their Google credentials instead of managing a separate password.
## Enabling Google SSO
To enable Google SSO for your account, go to the `Settings -> Account` page in the admin portal and click the **`Enable Google Login`** button.
## Enabling Google SSO for a sub-domain or custom domain
Your customers and resellers can log in to the customer and reseller portals using Cryptlex sub-domain or custom domain URLs only. To enable Google SSO for these URLs, you first need to create a Google Client ID for the sub-domain or custom domain.
### Creating the Google Client ID
* In the [Google Cloud Console](https://console.cloud.google.com/apis/credentials), select or create a project, then go to `APIs & Services -> Credentials`.
* If prompted, configure the OAuth consent screen (branding) for your project first.
* Click **`Create credentials`** and select **`OAuth client ID`**.
* Set the **Application type** to **`Web application`**.
* In the **Authorized JavaScript origins** field, add the sub-domain or custom domain URLs, such as `https://mycompany.customer.cryptlex.com` and `https://mycompany.reseller.cryptlex.com`.
* Create the client and copy the Client ID.
Then go to the `Settings -> Account` page in the admin portal, click the **`Configure Google SSO`** button, and paste the Client ID.
---
# SAML SSO
Section: SSO
URL: https://cryptlex.com/docs/sso/saml-sso
Summary: Cryptlex supports SAML single sign-on with auto-provisioning and role mapping for providers like Okta, Auth0, OneLogin, and Active Directory.
Last updated: 2026-08-19
Single sign-on (SSO) allows users of your Cryptlex account to log in using your existing SAML-enabled identity provider, such as Active Directory, OneLogin, Auth0, and Okta. This reduces the number of passwords your users need to manage and simplifies provisioning new users.
SAML SSO can be configured at two levels:
- **Account level**: Your team members configure SAML SSO for your Cryptlex account using your identity provider, covering admin portal login and, through role mapping, customer and reseller portal login.
- **Organization level**: An [organization admin](https://cryptlex.com/docs/customers/organizations) can configure SAML SSO for their own organization from the customer portal, so the organization's users log in to the customer portal with the organization's own identity provider.
## Configuring account-level SAML SSO
To get started, go to the `Settings -> Account` page in the admin portal and click the **`Configure SAML SSO`** button. This displays the SAML SSO settings dialog where you can add details of your identity provider.
Cryptlex supports the SAML 2.0 standard. Each identity provider has its own interface and nuances, but most provide configuration metadata as a URL, so this article covers configuration with a generic SAML identity provider.
The easiest way to configure SSO is to use a link to your identity provider's metadata file. Enter the URL in the **SAML IdP Metadata URL** input box and click **`Save`**. Cryptlex downloads the configuration file, parses it, and configures everything.
## Auto-provisioning users
The SAML identity provider must be configured to provide four attributes: **Email**, **FirstName**, **LastName**, and **Role**. These attributes allow Cryptlex to identify and automatically provision users.
**FirstName**, **LastName**, and **Role** are only required if the auto-provisioning of users is enabled.
Enter the attribute names your identity provider sends in the **Email Attribute**, **First Name Attribute**, **Last Name Attribute**, and **Role Attribute** fields in the SAML SSO settings dialog. Each field accepts multiple attribute names separated by commas, matched case-insensitively.
If you leave these fields empty, Cryptlex falls back to well-known attribute names, including the standard SAML claim URIs (for example, `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`) and common names like `Email`, `FirstName`, `LastName`, and `Role`.
If the IdP sends more than one role, Cryptlex applies a predefined priority order to determine the effective role for that session.
Priority order (highest to lowest): `admin`, `organization-admin`, `reseller-admin`, `user`.
### Role mapping
You can map the roles created in Cryptlex (service provider roles) to your existing roles in the identity provider. Depending on the identity provider role in the SAML assertion, Cryptlex uses the corresponding service provider role when auto-provisioning the user.
Ensure that the roles are correctly mapped in your Cryptlex SSO settings.
Team members must log in through the admin portal, customers (including users and organization admins) must access the customer portal, and reseller admins must use the reseller portal.
For the correct portal URLs, go to the [`Settings -> Customizations`](https://app.cryptlex.com/settings/customizations) page in the admin portal.
## Configuring organization-level SAML SSO
Organization admins can set up SAML SSO for their organization from the customer portal, using the organization's own identity provider. Once configured, users belonging to the organization authenticate against that identity provider when logging in to the customer portal, instead of using Cryptlex credentials or your account-level identity provider.
---
# Deprecations
Section: Changelogs
URL: https://cryptlex.com/docs/changelogs/deprecations
Summary: A dated log of every deprecation across the Cryptlex Web API and SDKs, with migration steps for each change.
Last updated: 2026-09-15
This page is a dated log of everything that has been deprecated across the Cryptlex Web API and SDKs, newest first. Each section covers one deprecation, what replaces it, and how to migrate. Deprecated items continue to work for backward compatibility, but you should update your integration to the replacements.
## Activation logs
**Deprecated in August 2026** (Web API 3.85.0)
Activation logs are no longer generated after 15 September 2026, and are replaced by activation events, a complete record of activation activity on a license, covering creation, updates, deactivations, lease expiries, and server syncs.
Activation logs are no longer generated after 15 September 2026.
To migrate:
Replace calls to the activation log endpoints in your Web API scripts with the activation events endpoints.
## The LA_SYSTEM permission flag
**Deprecated in December 2025** (LexActivator 3.38.0)
The `LA_SYSTEM` permission flag is replaced by `LA_ALL_USERS`, which enables system-wide activation: one activation shared by every OS user on the machine, without requiring your app to run with administrator privileges. It is supported on Windows and macOS, and the license's **User locked** property is ignored for system-wide activations.
To migrate, pass `LA_ALL_USERS` instead of `LA_SYSTEM` to `SetProductId()`. LexActivator 3.38.0 also added support for migrating existing activation data from `LA_USER` and `LA_SYSTEM` to `LA_ALL_USERS`, so machines that are already activated keep their activation after the change. See the permission flag guidance in [Best Practices](https://cryptlex.com/docs/sdks-and-apis/best-practices).
## Validity and expiration strategy on maintenance policies
**Deprecated in November 2025** (Web API 3.81.0)
The `validity` and `expirationStrategy` properties on maintenance policies are replaced by `subscriptionInterval` and `subscriptionStartTrigger`, [the same model licenses moved to](#validity-and-expiration-strategy-on-licenses).
To migrate:
1. Update each maintenance policy, in the admin portal or through the Web API, to use a subscription interval and start trigger instead of validity and expiration strategy.
2. If your scripts create or update maintenance policies through the Web API, send `subscriptionInterval` and `subscriptionStartTrigger` instead of `validity` and `expirationStrategy`.
Existing maintenance policies keep working, and no SDK changes are required.
## Trial activation extend endpoint
**Deprecated in September 2025** (Web API 3.80.0)
The `POST /v3/trial-activations/:id/extend` endpoint is replaced by [`PATCH /v3/trial-activations/:id/expires-at`](https://cryptlex.com/reference/web-api/patch-trial-activations-id-expires-at).
To migrate, replace calls to the extend endpoint with the expires-at endpoint, and send the exact new expiration date instead of a duration to add.
## Product versions and feature flags
**Deprecated in May 2025** (Web API 3.78.0, LexActivator 3.32.0, LexFloatClient 4.11.0)
Product versions and feature flags are replaced by [features and Entitlement Sets](https://cryptlex.com/docs/features-and-entitlements/overview):
- Product versions (`/v3/product-versions`) are replaced by [Entitlement Sets](https://cryptlex.com/docs/features-and-entitlements/features-and-entitlement-sets) (`/v3/entitlement-sets`), which group features into named tiers.
- Feature flags (`/v3/feature-flags`) are replaced by features (`/v3/features`) and feature entitlements, which support per-license overrides that feature flags did not.
To migrate:
1. Recreate your product versions as Entitlement Sets and your feature flags as features, then link an Entitlement Set to each license template and license. See [Features and Entitlement Sets](https://cryptlex.com/docs/features-and-entitlements/features-and-entitlement-sets).
2. Update Web API scripts that call `/v3/product-versions` or `/v3/feature-flags` to use `/v3/entitlement-sets` and `/v3/features`.
3. Replace the deprecated SDK functions with their replacements:
SDK
Deprecated
Replacement
LexActivator
`GetProductVersionName()`
`GetLicenseEntitlementSetName()`
LexActivator
`GetProductVersionDisplayName()`
`GetLicenseEntitlementSetDisplayName()`
LexActivator
`GetProductVersionFeatureFlag()`
`GetFeatureEntitlement()`
LexFloatClient
`GetHostProductVersionName()`
`GetHostLicenseEntitlementSetName()`
LexFloatClient
`GetHostProductVersionDisplayName()`
`GetHostLicenseEntitlementSetDisplayName()`
LexFloatClient
`GetHostProductVersionFeatureFlag()`
`GetHostFeatureEntitlement()`
See [Accessing feature entitlements](https://cryptlex.com/docs/features-and-entitlements/accessing-feature-entitlements) for how the replacement functions work.
Offline activation response files generated before this release (22 May 2025) do not contain the feature-entitlement fields and cannot be consumed by `ActivateLicenseOffline()` in newer SDK versions; generate a fresh response file for those machines. Activations already stored on a machine are not affected and remain backward compatible across SDK upgrades.
## Validity and expiration strategy on licenses
**Deprecated in May 2025** (Web API 3.78.0)
The `validity` and `expirationStrategy` properties on licenses and license templates are replaced by `subscriptionInterval` and `subscriptionStartTrigger`. See [Subscription Licensing](https://cryptlex.com/docs/licensing-models/subscription-licensing) for how the new model works.
The migration requires no changes in LexActivator, LexFloatClient, or LexFloatServer; all functionality continues to work as before. Backward compatibility is fully maintained, so existing licenses using validity keep working.
To use the new model for future licenses, update each license template:
1. Clear the **Validity** and **Expiration Strategy** fields.
2. Set the **Subscription Interval** (for example, `1 month` instead of `30 days`) and the **Subscription Start Trigger**:
- Use **License Creation** if the old expiration strategy was _Immediate_.
- Use **License Activation** if it was _Delayed_.
Modifying a license template does not affect existing licenses. You can either keep them on validity (the renewal and extension APIs remain supported) or migrate each license using the **`Update Subscription Parameters`** action from the Actions menu in the license table, setting the **Subscription Interval** and the appropriate **Start Trigger**.
A script using the Web API is available on request to automate this update for multiple licenses. Contact us through the [contact page](https://cryptlex.com/contact).
The duration-based extend endpoints are also deprecated. Replace them with the expires-at endpoints, which take an exact expiration date instead of a duration:
Deprecated
Replacement
`POST /v3/licenses/:id/extend`
[`PATCH /v3/licenses/:id/expires-at`](https://cryptlex.com/reference/web-api/patch-licenses-id-expires-at)
`POST /v3/licenses/:id/maintenance/extend`
[`PATCH /v3/licenses/:id/maintenance/expires-at`](https://cryptlex.com/reference/web-api/patch-licenses-id-maintenance-expires-at)
`license.extended` webhook event
`license.expiresAt.updated` webhook event
## The disableClockValidation property
**Deprecated in June 2024** (Web API 3.72.0)
The `disableClockValidation` property on licenses is replaced by `allowedClockOffset`.
To migrate, set `allowedClockOffset` to `-1` instead of setting `disableClockValidation` to `true` when creating or updating licenses and license templates.
## The CheckForReleaseUpdate function
**Deprecated in April 2023** (LexActivator 3.21.0)
The `CheckForReleaseUpdate()` function is replaced by `CheckReleaseUpdate()`, whose callback also reports whether the update is allowed for the license.
To migrate, replace the function call and update your callback to handle the release object and the update-allowed status. See [Auto-Updates](https://cryptlex.com/docs/releases/auto-updates) for a complete example.
## The SetAppVersion function
**Deprecated in June 2022** (LexActivator 3.19.0)
The `SetAppVersion()` function and the `appVersion` property on activations are replaced by `SetReleaseVersion()` and the `releaseVersion` property.
To migrate, call `SetReleaseVersion()` with your app's dot-separated version (for example, `1.2.3`) instead of `SetAppVersion()`. The value is stored on the activation as `releaseVersion` and is also what [maintenance policies](https://cryptlex.com/docs/licensing-models/software-maintenance-and-support) validate against.
## Filter query parameters
**Deprecated in September 2021** (Web API 3.44.0)
The fixed filter query parameters listed below are replaced by query operators.
Deprecated
Replacement
Endpoints
`createdAfter`, `createdBefore`
`createdAt[gt]`, `createdAt[lt]`
`/v3/licenses`, `/v3/users`, `/v3/activation-logs`
`lastSeenAfter`, `lastSeenBefore`
`lastSeenAt[gt]`, `lastSeenAt[lt]`
`/v3/users`
`metadataKey`, `metadataValue`
`metadata.key`, `metadata.value`
`/v3/licenses`, `/v3/users`, `/v3/activations`
`email`
`user.email`
`/v3/licenses`
To migrate, replace each deprecated parameter with its operator form. For example, `createdAfter=2021-01-01` becomes `createdAt[gt]=2021-01-01`.
## The roles property on users
**Deprecated in December 2018** (Web API 3.9.0)
The `roles` array on users is replaced by a single `role` property.
To migrate, update scripts that read or set `roles` on the `/v3/users` endpoints to use `role`.
## Where deprecations are announced
When something is deprecated, it is noted in the corresponding changelog ([Web API](https://cryptlex.com/docs/changelogs/web-api), [LexActivator](https://cryptlex.com/docs/changelogs/lexactivator), [LexFloatClient](https://cryptlex.com/docs/changelogs/lexfloatclient), [LexFloatServer](https://cryptlex.com/docs/changelogs/lexfloatserver)) and added to this page.
---
# Web API
Section: Changelogs
URL: https://cryptlex.com/docs/changelogs/web-api
Summary: Changelog for the Cryptlex Web API, covering new endpoints, properties, webhook events, and deprecations in each version.
Last updated: 2026-09-15
export const WEB_API_REFERENCE_BASE = "/reference/web-api"
## 3.85.0 (2026-08-17)
### Added
* Support for sandbox environments, which are isolated environments for testing managed through the `/v3/environments` endpoint, each with its own products, licenses, users, and activations, along with per-environment resource caps and team member access.
* Support for two-factor authentication enforcement, so accounts can set the date from which 2FA becomes mandatory, separately for team members and for end users, with a grace period measured from account creation. `twoFactorRequiredFrom` is returned to clients before the deadline, and after it logins and token refreshes without 2FA are rejected with `TWO_FACTOR_ENFORCEMENT_REQUIRED`.
* Activation events, a complete record of activation activity on a license (create, update, deactivate, lease expiry, and server sync), filterable by license, activation, event type, `userId`, and `organizationId`.
* `POST /v3/licenses/lookup` endpoint, which returns a license's key and type for a given `accountId`, `productId`, and license key, so the license type can be checked before activation.
* `POST /v3/webhooks/:id/test` endpoint, which delivers a sample payload to a webhook endpoint and returns the response, the exact signed body, and the signature.
* `channel` query param to the `GET /v3/organizations/:organizationId/releases` endpoint.
### Deprecated
* Activation logs (use activation events instead).
## 3.84.0 (2026-07-01)
### Added
* `POST /v3/licenses/:id/rotate` endpoint to rotate the license key of a license.
* Organization-level SAML SSO settings through the `/v3/organizations/:id/saml-configuration` endpoint, so organization admins can configure their own identity provider for logging in to the customer portal.
* `iconUrl` property to products. The product icon and description are now shown in the customer portal.
* Support for creating users with the same email as an admin user, for testing purposes.
* `PATCH /v3/resellers/:resellerId/licenses/:id/expires-at` endpoint for resellers to update the expiration date of a license, including renewing it.
* `GET /v3/release-download-events` and `GET /v3/release-download-events/export` endpoints to track when and by whom your releases are downloaded.
### Updated
* **Breaking change**: API responses no longer include child entities unless they are requested with the `include` query param.
* The reseller admin role is now editable.
* Updating the expiration date of a license now instantly updates the `expiresAt` of all its activations, without waiting for their next server sync.
## 3.83.0 (2026-04-01)
### Added
* `userId` field to the `GET /v3/me/activations` endpoint response.
* Support for the `account.trial.expired` webhook event.
* `GET /v3/audit-logs/export` endpoint to export audit logs.
* `{{organization.name}}` placeholder for use in automated email templates.
* Support for a minimum `serverSyncInterval` of 180 seconds across all plans.
* `productId` query param to the `GET /v3/me/activations` endpoint.
### Updated
* Audit logs now store the actor's name and email directly in the response using `actorName` and `actorEmail`, making logs immutable even if the admin user details change later.
## 3.82.0 (2026-02-11)
### Added
* Tier support for Entitlement Sets.
* Support for the `organizationId` filter in the `GET /v3/activations` endpoint.
* `lastUsedAt` property to the `GET /v3/licenses` endpoint response.
* `[ne]` operator support for the organization filter in the `GET /v3/licenses` endpoint.
* `PATCH /v3/trial-activations/:id` endpoint for updating a trial activation.
### Updated
* Improved SSO role mapping to better handle multiple roles received from the identity provider (IdP).
## 3.81.0 (2025-11-24)
### Added
* `expiresAt` property to the license feature entitlements.
* `lastUsedAt` property to the personal access tokens.
* `subscriptionInterval` and `subscriptionStartTrigger` properties to maintenance policies.
* Webhooks are now suspended instead of being disabled, to ensure webhook event logs are still created even if webhooks fail, so that they can be manually retried later.
* `userId` query param to the `/v3/activations` endpoint.
* `maintenanceExpireAt` query param to the `/v3/licenses` endpoint.
### Deprecated
* `validity` property on maintenance policies (use `subscriptionInterval` instead).
* `expirationStrategy` property on maintenance policies (use `subscriptionStartTrigger` instead).
## 3.80.0 (2025-09-24)
### Added
* Subscription logs to track all license subscription changes, such as renewals, expiration updates, and interval modifications.
* `license.first-activated` webhook event that triggers when a license is activated for the first time.
* `license.expiresAt.updated` webhook event that triggers when the license expiration date changes.
* /v3/trial-activations/:id/expires-at endpoint to allow updating the expiration date of a trial activation directly, rather than using the deprecated extend endpoint.
* /v3/activations endpoint to allow bulk deletion of activations within a date range for a specific license.
* `organization.user.created` and `reseller.user.created` events for automated emails.
* `entitlementSetId` and `activation.countryCode` query params to the `/v3/licenses` endpoint.
## 3.79.0 (2025-08-11)
### Added
* `activation.lease-expired` webhook event that triggers when an activation lease expires without renewing.
* `license.activation.limit-reached` webhook event that triggers when the maximum allowed activations are reached for a license.
* `license.subscription.updated` webhook event that triggers when the license subscription properties are updated.
* `subscriptionInterval` and `subscriptionStartTrigger` query params to the `/v3/licenses` endpoint.
## 3.78.0 (2025-05-22)
### Added
* Entitlement Sets and features.
* License level features and feature overriding.
* `subscriptionInterval` and `subscriptionStartTrigger` properties to licenses.
* /v3/licenses/:id/expires-at endpoint to allow updating the license expiration date.
* `activation.lastSyncedAt` query param to the `/v3/licenses` endpoint.
* Response JSON in delete operations to audit logs.
### Deprecated
* Product versions (use Entitlement Sets instead).
* Feature flags (use features instead).
* `validity` property on license (use `subscriptionInterval` instead).
* `expirationStrategy` property on license (use `subscriptionStartTrigger` instead).
* `/v3/licenses/:id/extend` endpoint (use the `/v3/licenses/:id/expires-at` endpoint instead).
## 3.77.0 (2025-02-07)
### Added
* Archive support for releases.
## 3.76.0 (2025-01-14)
### Added
* OpenTelemetry support.
## 3.75.0 (2024-11-19)
### Added
* Query params for reseller license and activation endpoints.
* Activation creation date to the activation JWT.
### Updated
* Limit the number of license metadata fields to 50 per license.
## 3.74.0 (2024-10-15)
### Added
* Support for refresh tokens in the login endpoint.
## 3.73.0 (2024-09-13)
### Added
* User and Organization resources in the activations export endpoint.
## 3.72.0 (2024-06-10)
### Added
* Support for using `-1` to represent unlimited value for `allowedActivations`, `allowedDeactivations`, `allowedFloatingClients`, `allowedClockOffset`, `leaseDuration`, `serverSyncGracePeriod` in the license resource.
* Support for `viewPermissions` for license metadata to control the visibility as per the user role.
* Support for `include` query param in the `/v3/activations` endpoint to conditionally get linked users and organizations.
### Deprecated
* `disableClockValidation` property in license (use `allowedClockOffset = -1` instead).
## 3.71.0 (2024-04-15)
### Added
* `LicenseKey` query param to the `/v3/activations` endpoint.
* `/v3/automated-emails/:id/preview` endpoint to support server previews for emails.
## 3.70.0 (2024-02-05)
### Added
* Maintenance mode support (in on-premise deployments) to prevent traffic during critical updates.
## 3.69.0 (2023-12-11)
### Added
* `in` operator support to the `type` query parameter in the `/v3/licenses` endpoint.
## 3.68.0 (2023-11-29)
### Added
* Query params to the `/v3/users/export` endpoint.
## 3.67.0 (2023-09-06)
### Added
* Support for resellers.
## 3.66.0 (2023-08-09)
### Added
* Organizations and related API endpoints for customer portal.
## 3.65.0 (2023-07-21)
### Added
* `/v3/license-templates` endpoint as an alternative for license policies.
* `productId` query param in the `/v3/me/licenses` endpoint.
## 3.64.0 (2023-05-30)
### Added
* `/v3/activations/export` endpoint to export all activations.
* All `/v3/licenses` endpoint query params to the `/v3/licenses/export` endpoint.
* `name` query param in the `/v3/users` endpoint.
* `createdAt` query param in the `/v3/organizations` endpoint.
## 3.63.0 (2023-04-06)
### Added
* `expired`, `metadata.key`, `metadata.value` and `createdAt` query params to the `/v3/trial-activations` endpoint.
## 3.62.0 (2023-04-04)
### Added
* `published` and `private` query params to the `/v3/releases` endpoint.
* `published` query param to the `/v3/release-files` endpoint.
* `action` query param to the `/v3/activation-logs` endpoint.
## 3.61.0 (2023-03-29)
### Added
* /v3/webhook-event-logs endpoint to get the log of all the triggered webhook events.
* /v3/automated-email-event-logs endpoint to get the log of all the triggered automated email events.
### Updated
* Renamed `email-templates` to `automated-emails` in login endpoint.
## 3.60.0 (2023-03-10)
### Added
* `license.maintenance-expired` and `license.maintenance-expiring-soon` events in webhooks and email templates.
* /v3/activation-logs/export endpoint to export activation logs in CSV format.
* `on` (organization name) and `oa` (organization address) properties in the activation JWT response.
## 3.59.0 (2023-03-08)
### Added
* /v3/organizations endpoint to add support for organizations.
## 3.58.0 (2023-02-21)
### Added
* `lcat` (license created at) and `laat` (license activated at) properties in the activation JWT response.
## 3.57.0 (2023-02-08)
### Added
* `expiresAt` and `expiringSoon` query params to the /v3/licenses endpoint.
* `offline` property to the activation log resource.
### Fixed
* Issue causing emails sent through SendGrid to fail.
## 3.56.0 (2022-12-14)
### Added
* `allowed` query param to the `/v3/releases/update` endpoint.
## 3.55.0 (2022-08-26)
### Added
* /v3/release-channels endpoint to add support for adding release channels.
* /v3/release-platforms endpoint to add support for adding release platforms.
## 3.54.0 (2022-06-13)
### Added
* /v3/maintenance-policies endpoint to add support for maintenance policies.
* /v3/licenses/:id/maintenance/renew endpoint to add support for renewing license maintenance.
* /v3/licenses/:id/maintenance/extend endpoint to add support for extending license maintenance.
* `maintenancePolicyId` property to the license resource.
* `currentReleaseVersion` property to the license resource.
* `maxAllowedReleaseVersion` property to the license resource.
* `releaseVersion` property to the activation resource.
## 3.53.0 (2022-06-01)
### Added
* {"/v3/activations/{id}/deactivate"} endpoint for secure deactivation of activations.
* Added `accountId` in login endpoint.
* Added `accountId` in activation, trial activation and deactivation endpoints.
* Added `accountId` in release update and latest endpoint.
* Added `accountId` in release download URL.
### Updated
* Renamed `companyId` to `accountAlias` in login endpoint.
## 3.52.0 (2022-03-28)
### Added
* `/v3/sending-domains` endpoint to add support for DMARC compliant emails.
## 3.51.0 (2022-02-11)
### Added
* `resourceId` query param to event logs.
## 3.50.0 (2022-01-27)
### Added
* `disableValidationCheck` property to the license resource.
## 3.49.0 (2021-12-01)
### Added
* `changes` property to the event log resource.
## 3.48.0 (2021-11-17)
### Added
* `allowClientLeaseDuration` property to the license resource.
## 3.47.0 (2021-11-01)
### Added
* /v3/product-versions endpoint to add support for product versions.
* /v3/feature-flags endpoint to add support for feature flags.
## 3.46.0 (2021-10-25)
### Added
* `user.created` event in the email templates.
* `user.reset-password-request` event in the email templates.
## 3.45.0 (2021-10-07)
### Added
* `private` property to the release resource.
* `license.deleted` event in the webhooks and email templates.
## 3.44.0 (2021-09-20)
### Added
* Query operators support.
* `user.company` query param to the `/v3/licenses` endpoint.
* `activation.appVersion` query param to the `/v3/users` endpoint.
### Deprecated
* `createdAfter` and `createdBefore` in the `/v3/licenses`, `/v3/users`, `/v3/activation-logs` endpoints. These can be replaced with `createdAt[gt]` and `createdAt[lt]` respectively.
* `lastSeenAfter` and `lastSeenBefore` in the `/v3/users` endpoint. These can be replaced with `lastSeenAt[gt]` and `lastSeenAt[lt]` respectively.
* `metadataKey` and `metadataValue` in the `/v3/licenses` and `/v3/users` endpoints. These can be replaced with `metadata.key` and `metadata.value` respectively.
* `email` in the `/v3/licenses` endpoint. This can be replaced with `user.email`.
## 3.43.0 (2021-08-05)
### Added
* `createdAfter` and `createdBefore` query params to /v3/activation-logs endpoint.
## 3.42.0 (2021-05-19)
### Added
* `allowCustomerPortalAccess` property to the user resource.
## 3.41.0 (2021-03-18)
### Added
* `offline` property to the activation resource.
## 3.40.0 (2021-03-10)
### Added
* /v3/users/export endpoint to add support for exporting the users in CSV format.
* /v3/trial-activations/export endpoint to add support for exporting the trial activations in the CSV format.
## 3.39.0 (2021-02-10)
### Added
* `additionalUserIds` property to the license resource.
## 3.38.0 (2021-01-28)
### Added
* {"/v3/licenses/meter-attributes/{id}/reset"} endpoint to add support for resetting the meter attributes.
* {"/v3/licenses/meter-attributes/{id}"} endpoint to add support for deleting the meter attributes.
* {"/v3/licenses/metadata/{id}"} endpoint to add support for deleting the metadata fields.
## 3.37.0 (2021-01-06)
### Added
* `appVersion` property to the activation log resource.
## 3.36.0 (2020-12-28)
### Added
* `floating` property to the meter attribute resource.
* `allowContainerActivation` property to the license and trial policy resources.
## 3.35.0 (2020-12-22)
### Added
* Support for caching to improve performance.
## 3.34.0 (2020-12-01)
### Updated
* Meter attributes are now persistent by default.
## 3.33.0 (2020-11-20)
### Added
* `visible` property to the meter attribute resource.
## 3.32.0 (2020-09-23)
### Added
* `allowedIpRanges` property to the license resource.
## 3.31.0 (2020-07-07)
### Added
* SAML SSO support.
## 3.30.0 (2020-06-06)
### Added
* `cc` and `bcc` properties to the email templates.
## 3.29.0 (2020-06-02)
### Added
* `expiringSoonEventOffset` property to the license policy and the license resources.
## 3.28.0 (2020-05-05)
### Added
* `metadataKey` and `metadataValue` query params to /v3/activations endpoint.
## 3.27.0 (2020-04-21)
### Added
* `allowedIpRange` property to the license resource.
## 3.26.0 (2020-03-28)
### Added
* /v3/email-templates endpoint to add support for email templates.
## 3.25.0 (2020-01-25)
### Added
* `keyPattern` property to the license policy resource.
## 3.24.0 (2019-11-18)
### Added
* `grossUses` property to the license meter attributes.
* `metadataKey` and `metadataValue` query params to the `/v3/users` endpoint.
## 3.23.0 (2019-10-20)
### Fixed
* Some minor bug fixes and improvements.
## 3.22.0 (2019-09-16)
### Added
* `product.displayName` property to the user release resource.
## 3.21.0 (2019-07-23)
### Added
* `disableGeoLocation` property to the license policy, trial policy and license resources, to prevent storing IP and location data.
* `downloads` property to the release file resource, to track number of downloads.
## 3.20.0 (2019-05-15)
### Added
* `requiredMeterAttributes` property to the license policy resource, to enforce meter attributes schema for the licenses.
* `meterAttributes` property to the license resource.
## 3.19.0 (2019-04-30)
### Added
* `requireAuthentication` property to the license resource, to enforce user authentication for license activation.
## 3.18.0 (2019-04-15)
### Added
* `resellerId` property to the license resource.
* `tags` property to the user resource.
## 3.17.0 (2019-04-12)
### Added
* /v3/docs#tag/ReleaseFiles endpoints to add support for external files in the releases.
## 3.16.0 (2019-04-10)
### Added
* /v3/accounts/login-google endpoint to enable login using Google SSO.
## 3.15.0 (2019-03-25)
### Added
* Support for [per-instance](https://cryptlex.com/docs/license-management/license-templates#leasing-strategy) leasing strategy for hosted-floating license type.
## 3.14.0 (2019-03-14)
### Added
* /v3/me/releases endpoint to display releases in the customer portal.
## 3.13.0 (2019-03-05)
### Added
* `license.expired` and `license.expiring-soon` events to webhooks.
* `account.logged-in` event to event log.
* Partial version comparison in [update](https://cryptlex.com/docs/releases/auto-updates#checking-for-updates-using-the-web-api) API endpoint for ignoring patch and build updates.
## 3.12.0 (2019-02-23)
### Added
* `displayName` to products resource.
## 3.11.0 (2019-02-20)
### Added
* /v3/status health check endpoint.
* Dynamic origin for password reset mails.
* `customDomain`, `website`, `logoUrl`, `faviconUrl` to accounts resource.
## 3.10.0 (2018-12-17)
### Added
* `leasingStrategy` property to licenses resource.
* `company` query param to users resource.
## 3.9.0 (2018-12-06)
### Added
* Support for referrals.
* `role` property to users resource deprecating `roles` property.
## 3.8.0 (2018-10-12)
### Added
* /v3/me/2fa-secret and /v3/me/2fa-recovery-codes endpoints to allow for two factor authentication.
## 3.7.0 (2018-09-12)
### Added
* /v3/trial-activations/offline-activate endpoint to allow for offline trial activations.
## 3.6.0 (2018-09-09)
### Added
* Support for bank deposits through the admin portal as alternative for credit cards.
## 3.5.0 (2018-08-06)
### Added
* `allowedClockOffset` property to license policies and licenses which can be used to allow license and trial activations on machines where system clocks run behind the network time.
* /v3/analytics/activations/app-version endpoint to retrieve activations by app version.
## 3.4.0 (2018-06-25)
### Added
* Distribution API for secure distribution of software applications and release management.
* /v3/users/:id/reset-password-token endpoint to allow implementation of forgot password functionality for custom branded portals.
## 3.3.0 (2018-06-09)
### Added
* /v3/licenses/:id/extend endpoint to allow extension of licenses. Before this only license renewal was allowed.
### Fixed
* Some minor bug fixes.
## 3.2.0 (2018-05-28)
### Added
* /v3/me and /v3/me/licenses endpoints for customer portal.
### Fixed
* Some minor bug fixes.
## 3.1.0 (2018-05-21)
### Added
* `licensePolicyId` property to licenses which can be used to override the default license policy of a license, inherited through product.
* `requiredMetadataKeys` property to license policies to make it must for a license to have required metadata keys when it is created. The metadata keys will automatically appear for licenses in the admin portal.
### Fixed
* Some minor bug fixes and improvements.
## 3.0.1 (2018-05-18)
### Updated
* Each license you create is counted as an activation irrespective of whether it is activated or not (as before). But if license allows more than one activation, then those are only counted when used.
* `allowedActivations` property in license policies and licenses can now be set to `0` also, to allow unlimited activations for any license.
* For on-premise floating licenses `allowedFloatingClients` are no longer counted as activations, which means floating licenses became cheaper.
### Fixed
* Some issues in floating licenses.
* Other minor bug fixes.
## 3.0.0 (2018-05-03)
### Added
* Completely new REST API.
* Beautiful API docs.
---
# LexActivator
Section: Changelogs
URL: https://cryptlex.com/docs/changelogs/lexactivator
Summary: Changelog for the LexActivator SDK, covering new functions, platform support, deprecations, and fixes in each version.
Last updated: 2026-09-30
## 3.46.0 (2026-09-30)
### Added
* Support for license key rotation. Existing activations switch to the new key on the next server sync; no reactivation needed.
### Updated
* Network requests are now synchronized per product across processes. This prevents conflicting activation, deactivation, and sync calls when multiple instances of an app run at the same time.
## 3.45.0 (2026-09-16)
### Added
* `GetDataStoreInfo()` function to get information about the data store used by LexActivator, including where activation data is stored.
## 3.44.0 (2026-08-31)
### Added
* `LookupLicense()` function to fetch license details, such as the license type, from the server without activating the license.
## 3.43.0 (2026-08-11)
### Added
* Added support for sandboxed environments.
## 3.42.2 (2026-07-15)
### Fixed
* Fixed a security vulnerability affecting offline license activation. Upgrading is strongly recommended.
## 3.42.1 (2026-05-25)
### Fixed
* Fixed license data invalidation caused by multi-process access conflicts on Windows (`LA_ALL_USERS`) and Linux.
## 3.42.0 (2026-04-21)
### Added
* Added crypto-binding support for Windows.
* Added support for 16 KB page sizes in LexActivator for Android.
## 3.41.1 (2026-04-14)
### Fixed
* Minor bug fixes.
## 3.41.0 (2026-04-07)
### Added
* `SyncTrialActivation()` function to perform a one-time synchronization with the server for refreshing local trial data such as trial metadata updates and server-side trial extensions.
* `SyncLicenseActivation()` function to perform a one-time synchronization with the server for refreshing local license data.
## 3.40.0 (2026-03-26)
### Added
* `baseValue` property added to the `FeatureEntitlement` object returned by `GetFeatureEntitlement()` function.
## 3.39.1 (2026-03-24)
### Fixed
* Minor bug fixes.
## 3.39.0 (2026-03-09)
### Added
* `GetLicenseEntitlementSetTier()` function returns the tier of the license entitlement set.
## 3.38.1 (2026-02-27)
### Fixed
* Improved proxy detection for Windows.
## 3.38.0 (2025-12-30)
### Added
* Added support for migration of activation data from `LA_USER` and `LA_SYSTEM` to `LA_ALL_USERS` for macOS and Windows.
## 3.37.0 (2025-12-11)
### Added
* `expiresAt` property added to the `FeatureEntitlement` object returned by `GetFeatureEntitlement()`.
* `totalActivations` and `totalDeactivations` properties added to the `UserLicense` object returned by `GetUserLicenses()`.
## 3.36.0 (2025-12-03)
### Added
* `GetLastActivationError()` returns the error code that caused the activation data to be cleared.
### Fixed
* Minor bug fix.
## 3.35.2 (2025-11-04)
### Fixed
* Minor bug fix.
## 3.35.1 (2025-10-21)
### Updated
* Improved proxy detection for Windows.
## 3.35.0 (2025-10-10)
### Added
* Added support for WSL detection.
## 3.34.2 (2025-09-24)
### Fixed
* Minor bug fix.
## 3.34.1 (2025-09-04)
### Fixed
* Minor bug fix.
## 3.34.0 (2025-09-02)
### Added
* Improved device fingerprint algorithm for Linux when using the `LA_SYSTEM` permission flag.
### Fixed
* Minor bug fix.
## 3.33.0 (2025-08-05)
### Added
* Support for `x86_64` architecture for Android packages.
### Updated
* `libcurl` version has been updated to v8.14.1.
## 3.32.3 (2025-05-28)
### Fixed
* Minor bug fix.
## 3.32.2 (2025-05-27)
### Fixed
* Minor bug fix.
## 3.32.1 (2025-05-27)
### Fixed
* Minor bug fix.
## 3.32.0 (2025-05-22)
### Added
* `GetLicenseEntitlementSetName()` function returns the name of the license entitlement set.
* `GetLicenseEntitlementSetDisplayName()` function returns the display name of the license entitlement set.
* `GetFeatureEntitlements()` function returns the list of feature entitlements associated with the license.
* `GetFeatureEntitlement()` returns a specific feature entitlement associated with the license.
* `GetActivationLastSyncedDate()` function returns the activation last synced date timestamp.
* Support for PowerPC32 architecture on Linux.
### Updated
* `ActivateLicense()` function now returns `LA_E_LICENSE_NOT_EFFECTIVE` if the license activation is attempted before its effective date.
* `IsLicenseGenuine()`, `IsLicenseValid()` functions now return `LA_E_FEATURE_ENTITLEMENTS_INVALID` if the feature entitlements are invalid.
### Deprecated
* `GetProductVersionName()` function has been deprecated in favour of `GetLicenseEntitlementSetName()` function.
* `GetProductVersionDisplayName()` has been deprecated in favour of `GetLicenseEntitlementSetDisplayName()` function.
* `GetProductVersionFeatureFlag()` has been deprecated in favour of `GetFeatureEntitlement()` function.
## 3.31.3 (2025-02-13)
### Fixed
* Improved linux fingerprinting stability for loose fingerprint matching strategy.
## 3.31.2 (2025-01-27)
### Fixed
* Improved error handling by adding `LA_E_FREE_PLAN_ACTIVATION_LIMIT_REACHED`.
## 3.31.1 (2025-01-09)
### Fixed
* Fixed `SetDebugMode()` behavior.
## 3.31.0 (2024-12-02)
### Added
* Support for Windows ARM64 builds.
* System-wide activations are now supported on macOS as well.
* `GetActivationCreationDate()` function returns the activation creation date timestamp for the current activation.
## 3.30.5 (2024-11-28)
### Fixed
* Bug fix.
## 3.30.4 (2024-11-27)
### Fixed
* Bug fix.
## 3.30.3 (2024-11-15)
### Fixed
* Bug fix.
## 3.30.2 (2024-11-14)
### Updated
* The `User-Locked` property is now ignored for system-wide activations.
## 3.30.1 (2024-10-30)
### Updated
* Signed builds for macOS.
### Fixed
* Resolved an issue with `LA_E_TIME` to allow license deactivation.
## 3.30.0 (2024-08-22)
### Added
* `GetUserLicenses()` function returns the license metadata as well.
### Updated
* Updated buffer sizes for various parameters of the Release struct in `LexTypes.h`.
## 3.29.0 (2024-08-05)
### Updated
* The minimum supported macOS version has been updated to 10.13.
* Updated the data type of `allowedUses` to `int64_t`, `totalUses` to `uint64_t` and `grossUses` to `uint64_t` of `GetLicenseMeterAttribute()` function.
* Updated the data type of argument from `uint32_t` to `int64_t` of `SetActivationLeaseDuration()` function.
* Updated the argument type from `uint32_t` to `int64_t` of `GetLicenseAllowedActivations()` function.
* Updated the argument type from `uint32_t` to `int64_t` of `GetLicenseAllowedDeactivations()` function.
* Updated the data types of `allowedActivations` and `allowedDeactivations` from `int` to `int64_t` of `UserLicense` struct.
## 3.28.0 (2024-04-25)
### Added
* `SetCacheMode()` function to disable or enable in-memory caching.
## 3.27.1 (2024-04-16)
### Fixed
* Minor bug fix.
## 3.27.0 (2024-03-28)
### Added
* `LA_ALL_USERS` permission flag to enable system-wide activation on Windows.
### Fixed
* Minor bug fix.
## 3.26.1 (2024-03-15)
### Fixed
* Minor bug fix.
## 3.26.0 (2024-02-09)
### Added
* `GetLicenseAllowedDeactivations()` function to get the allowed deactivations of the license.
* `GetLicenseTotalDeactivations()` function to get the total deactivations of the license.
### Fixed
* Minor bug fix.
## 3.25.2 (2024-01-17)
### Fixed
* Minor bug fix.
## 3.25.1 (2024-01-02)
### Fixed
* Minor bug fix.
## 3.25.0 (2023-12-01)
### Added
* `GetActivationId()` function to get the activation ID.
* Added support for EU data center.
## 3.24.1 (2023-10-10)
### Fixed
* Minor bug fix.
## 3.24.0 (2023-09-27)
### Added
* `AuthenticateUserWithIdToken()`function to authenticate the user via the OIDC ID token.
## 3.23.3 (2023-09-23)
### Fixed
* Minor bug fix.
## 3.23.2 (2023-09-21)
### Fixed
* Minor bug fix.
## 3.23.1 (2023-09-05)
### Fixed
* Added missing check for the existence of meter attribute before incrementing, decrementing and resetting the count.
* Added missing server sync in the case when `IsLicenseGenuine()` function returns `LA_E_RELEASE_VERSION_NOT_ALLOWED` error code.
## 3.23.0 (2023-08-10)
### Added
* `SetTwoFactorAuthenticationCode()` function to authenticate the users with 2FA enabled.
### Fixed
* Fingerprint-related issues in Android devices.
## 3.22.0 (2023-07-31)
### Added
* `AuthenticateUser()` function to authenticate the user.
* `GetUserLicenses()` function to get the licenses linked with the user.
* `GetLicenseCreationDate()` function to get the creation date timestamp of the license.
* `GetLicenseActivationDate()` function to get the activation date timestamp of the license.
## 3.21.5 (2023-06-23)
### Fixed
* Minor bug fix.
## 3.21.4 (2023-06-03)
### Fixed
* Activation validation issue due to a very large number of metadata fields.
## 3.21.3 (2023-05-31)
### Fixed
* Crash in some OEM Android devices due to GSF ID.
* Fingerprint-related issue in Android devices of the same make.
## 3.21.2 (2023-04-17)
### Fixed
* Minor bug fixes.
## 3.21.1 (2023-04-10)
### Fixed
* Minor bug fixes.
## 3.21.0 (2023-04-06)
### Added
* `GetLicenseOrganizationName()` function to get the license organization name.
* `GetLicenseOrganizationAddress()` function to get the license organization address.
* `CheckReleaseUpdate()` function to check whether a new release is available for the product. It also determines if the update is allowed or not and provides the release object if a new release is available.
### Deprecated
* `CheckForReleaseUpdate()` function has been deprecated in favour of `CheckReleaseUpdate()` function.
## 3.20.9 (2023-02-10)
### Fixed
* False positive container detection on some Linux distributions.
## 3.20.8 (2023-02-10)
### Fixed
* Container detection issue on recent Linux distributions.
## 3.20.7 (2022-12-01)
### Fixed
* Encoding issue in `GetProductVersionName()` function.
## 3.20.6 (2022-11-22)
### Fixed
* Issue preventing detection of Windows Server 2022.
## 3.20.5 (2022-11-17)
### Fixed
* NTLM proxy authentication issue.
## 3.20.4 (2022-11-14)
### Fixed
* Fingerprint issue in Android trial activations.
## 3.20.3 (2022-11-11)
### Fixed
* Missing OS version in the case of some Windows server machines.
## 3.20.2 (2022-11-04)
### Fixed
* Minor bug fixes.
## 3.20.1 (2022-11-02)
### Fixed
* Minor bug fixes.
## 3.20.0 (2022-11-01)
### Added
* `GetLicenseMaxAllowedReleaseVersion()` function to get the maximum allowed release version of the license.
* `SetReleaseChannel()` function to set the release channel e.g. stable, beta etc. of the application.
* `SetReleasePlatform()` function to set the release platform e.g. windows, macos, linux etc. of the application.
* `SetReleasePublishedDate()` function to set the release published date of your application.
## 3.19.2 (2022-08-10)
### Fixed
* Removed external `libcurl` dependency in Linux `musl` build.
## 3.19.1 (2022-06-18)
### Fixed
* Minor bug fixes.
## 3.19.0 (2022-06-14)
### Added
* `GetActivationMode()` function to get the mode of activation (online or offline).
* `GetLicenseMaintenanceExpiryDate()` function to get the expiry date of maintenance.
* `SetReleaseVersion()` function to set the release version.
## 3.18.2 (2022-04-25)
### Fixed
* Issues related to device fingerprinting on Android.
## 3.18.1 (2022-04-05)
### Updated
* Dropped dependency on system `libcurl` in the case of Alpine Linux (musl).
## 3.18.0 (2022-01-27)
### Added
* Support for `disableClockValidation` license property.
## 3.17.2 (2021-12-08)
### Fixed
* PAC file related issue on Windows.
* False positives in VM detection for macOS.
## 3.17.1 (2021-11-30)
### Fixed
* Issue causing crash when PAC file is used for proxy settings on Windows.
## 3.17.0 (2021-11-17)
### Added
* `SetActivationLeaseDuration()` function to allow setting lease duration from the client.
## 3.16.0 (2021-11-02)
### Added
* `GetProductVersionName()` function to get the product version name.
* `GetProductVersionDisplayName()` function to get the product version display name.
* `GetProductVersionFeatureFlag()` function to get the product version feature flag.
## 3.15.4 (2021-09-30)
### Fixed
* Issue related to incorrect system encodings.
## 3.15.3 (2021-09-29)
### Fixed
* Issue causing failure in the detection of AWS EC2 VMs.
## 3.15.2 (2021-08-23)
### Fixed
* Issue causing `IsLicenseGenuine()` function to return incorrect status code in case of multi-product usage.
## 3.15.1 (2021-08-04)
### Fixed
* Issue causing crash on iOS in case of static linking.
* Issue causing crash on 32-bit Windows in case of Java.
## 3.15.0 (2021-07-14)
### Added
* Support for Android and iOS.
* Support for auto-proxy detection from PAC file on Windows.
* `SetDataDirectory()` function to allow changing the default directory used by LexActivator to store the activation data.
## 3.14.9 (2021-05-11)
### Fixed
* Issue causing `GetActivationMeterAttributeUses()` function to return incorrect value in case `LA_IN_MEMORY` flag is used.
## 3.14.8 (2021-05-06)
### Fixed
* Issue causing networking errors on Windows.
## 3.14.7 (2021-04-22)
### Fixed
* Issue causing license callback to get invoked even after the license was deactivated.
### Updated
* Dropped dependency on `libnss3` for Linux.
## 3.14.6 (2021-03-24)
### Fixed
* Issue in offline activation when offline response file of some other machine is used for activation.
## 3.14.5 (2021-02-25)
### Fixed
* Issue causing license callback of deactivated activation to trigger in the case when license deactivation fails.
## 3.14.4 (2021-02-24)
### Fixed
* Intermittent crashes in multi-threaded usage.
## 3.14.3 (2021-02-12)
### Fixed
* Improved performance of incrementing meter attributes in `LA_IN_MEMORY` mode.
## 3.14.2 (2021-01-25)
### Fixed
* Intermittent crashes in multi-threaded usage.
## 3.14.1 (2021-01-18)
### Fixed
* Buffer overflow issues causing activation verification to fail.
## 3.14.0 (2021-01-11)
### Added
* Support for preventing activation of license inside the container.
## 3.13.1 (2020-12-28)
### Fixed
* Intermittent crashes on high concurrent usage.
## 3.13.0 (2020-12-03)
### Updated
* Internal implementation of incrementing meter attributes resulting in increased performance and better concurrency support.
## 3.12.2 (2020-11-25)
### Fixed
* Caching issue causing `IsLicenseGenuine()` function to return `LA_FAIL` when multiple instances of the app are run on the same machine.
## 3.12.1 (2020-10-23)
### Fixed
* Issue causing LexActivator to be flagged as a malicious file by anti-viruses on Windows.
## 3.12.0 (2020-09-16)
### Added
* Support for bypassing system proxy settings. Just add `api.cryptlex.com` to the bypass proxy hosts list in the system proxy settings.
### Updated
* `DeactivateLicense()` function doesn't reset the license key in case of `hosted-floating` license type.
## 3.11.1 (2020-08-18)
### Fixed
* Bug causing the cache to return incorrect status code.
## 3.11.0 (2020-07-14)
### Added
* `SetCustomDeviceFingerprint()` function to allow setting a custom device fingerprint.
* `GetLicenseAllowedActivations()` function to get the allowed activations of the license.
* `GetLicenseTotalActivations()` function to get the total activations of the license.
* `GetLibraryVersion()` function to get the library version.
### Updated
* `GetLicenseMeterAttribute()` function to return gross uses of the meter attribute.
### Fixed
* Bug causing fingerprint mismatch error in Dockers.
## 3.10.1 (2020-06-12)
### Added
* Improved device fingerprinting of devices running Linux.
## 3.10.0 (2020-06-01)
### Added
* Improved device fingerprinting of devices running Linux.
### Fixed
* Bug preventing auto-detection of system proxy.
## 3.9.3 (2020-05-14)
### Fixed
* Bug causing crash in multi-threaded use.
## 3.9.2 (2020-04-20)
### Fixed
* Minor bug fixes.
## 3.9.1 (2020-04-14)
### Fixed
* Bug preventing the detection of Hyper-V on some Windows 10 machines.
## 3.9.0 (2020-03-28)
### Added
* LexActivator functions are now thread-safe.
### Fixed
* Minor bug fixes.
## 3.8.0 (2019-11-18)
### Added
* `SetOfflineActivationRequestMeterAttributeUses()` function to support meter attributes for offline activations.
### Fixed
* Minor bug fixes.
## 3.7.2 (2019-10-02)
### Fixed
* Minor bug fixes.
## 3.7.1 (2019-07-02)
### Fixed
* Minor bug fixes.
## 3.7.0 (2019-05-15)
### Added
* `GetActivationMeterAttributeUses()`, `IncrementActivationMeterAttributeUses()`, `DecrementActivationMeterAttributeUses()`, `ResetActivationMeterAttributeUses()` and `GetLicenseMeterAttribute()` functions to add support for meter attributes.
### Updated
* LexActivator wrappers for all the languages have been updated with above mentioned API function. Please update your wrappers using the latest code on [Github](https://github.com/cryptlex).
## 3.6.0 (2019-04-30)
### Added
* `SetLicenseUserCredential()` function for user authentication. If `requireAuthentication` property of license is set to `true` then this function must be called before invoking `ActivateLicense()` or `IsLicenseGenuine()` function.
## 3.5.0 (2019-04-04)
### Added
* `GetLicenseUserCompany()` and `GetLicenseUserMetadata()` functions to fetch user company and user metadata.
* `GetServerSyncGracePeriodExpiryDate()` function to get the grace period expiry date for server sync.
* `CheckForReleaseUpdate()` function to easily detect the [software updates](https://cryptlex.com/docs/releases/auto-updates#checking-for-updates-using-lexactivator) in your app.
## 3.4.0 (2019-03-25)
### Added
* `LA_IN_MEMORY` flag to add support for in-memory license activations, which stores license activation data in memory only instead of disk.
## 3.3.1 (2018-12-17)
### Fixed
* A bug preventing changing of permission flag from `LA_SYSTEM` to `LA_USER` when former is set first.
## 3.3.0 (2018-09-12)
### Added
* `GenerateOfflineTrialActivationRequest()` and `ActivateTrialOffline()` functions to allow for offline trial activations.
### Updated
* Wrappers for languages have been updated with `GenerateOfflineTrialActivationRequest()` and `ActivateTrialOffline()` API functions. Please update your wrappers using the latest code on [Github](https://github.com/cryptlex).
## 3.2.0 (2018-08-20)
### Added
* `GetLicenseType()` function to get the license type (node-locked or hosted-floating).
### Updated
* Wrappers for languages have been updated with `GetLicenseType()` API function. Please update your wrappers using the latest code on [Github](https://github.com/cryptlex).
## 3.1.0 (2018-08-06)
### Added
* Support for clock offset property set for the licenses in the admin portal, which can be used to allow license and trial activations on machines where system clocks run behind the network time.
### Updated
* Time tampering detection threshold has been increased to around one hour to allow for daylight savings and minor changes in the system time.
* On time tampering detection instead of returning `LA_E_TIME` it now returns `LA_E_TIME_MODIFIED`.
Now `LA_E_TIME` is returned only when the system time is behind the network time by more than the allowed clock offset.
### Updated
* Wrappers for languages have been updated with `LA_E_TIME_MODIFIED` status code. Please update your wrappers using the latest code on [Github](https://github.com/cryptlex).
## 3.0.5 (2018-07-21)
### Fixed
* A bug causing crash on few Windows machines, with WMIC service not running.
## 3.0.4 (2018-07-18)
### Fixed
* A bug causing crash on Linux, if license is deleted server side.
## 3.0.3 (2018-06-14)
### Fixed
* A bug causing insufficient system permissions error on first run on Linux.
## 3.0.2 (2018-05-30)
### Fixed
* A network SSL issue causing activations to fail for few proxies.
## 3.0.1 (2018-05-10)
### Fixed
* A network issue causing activations to fail.
## 3.0.0 (2018-05-03)
### Added
* `SetProductData()` function.
* `SetLicenseCallback()` function.
* `SetTrialActivationMetadata()` function.
* `SetAppVersion()` function.
* `GetProductMetadata()` function.
* `GetLicenseUserEmail()` function.
* `GetLicenseUserName()` function.
* `GetTrialActivationMetadata()` function.
* `GetTrialExpiryDate()` function.
* `GetTrialId()` function.
* `GetLocalTrialExpiryDate()` function.
* `IsLocalTrialGenuine()` function.
* `ExtendLocalTrial()` function.
* `Reset()` function.
### Updated
* All status codes have been updated.
* Renamed `SetVersionGUID()` function to `SetProductId()`.
* Renamed `SetProductKey()` function to `SetLicenseKey()`.
* Renamed `SetExtraActivationData()` function to `SetActivationMetadata()`.
* Renamed `ActivateProduct()` function to `ActivateLicense()`.
* Renamed `DeactivateProduct()` function to `DeactivateLicense()`.
* Renamed `ActivateProductOffline()` function to `ActivateLicenseOffline()`.
* Renamed `IsProductGenuine()` function to `IsLicenseGenuine()`.
* Renamed `IsProductActivated()` function to `IsLicenseValid()`.
* Renamed `GetExtraActivationData()` function to `GetActivationMetadata()`.
* Renamed `GetCustomLicenseField()` function to `GetLicenseMetadata()`.
* Renamed `GetProductKeyExpiryDate()` function to `GetLicenseExpiryDate()`.
* Renamed `InitializeTrial()` function to `ActivateLocalTrial()`.
### Deleted
* `GetDaysLeftToExpiration()` function.
* `SetTrialKey()` function.
* `ExtendTrial()` function.
* `GetTrialDaysLeft()` function.
* `SetDayIntervalForServerCheck()` function.
* `SetGracePeriodForNetworkError()` function.
* `SetUserLock()` function.
## 2.9.6 (2017-11-19)
### Added
* `GetProductKeyExpiryDate()` function to get the product key expiry timestamp.
* Support for Linux ARMv8 64 bit architecture.
## 2.9.5 (2017-10-19)
### Fixed
* Bug causing grace period not to expire on no server sync.
## 2.9.4 (2017-09-23)
### Fixed
* Bug causing incorrect detection of Hyper-V.
## 2.9.3 (2017-09-09)
### Fixed
* Bug causing grace period not to expire.
* Regression causing `LA_EXPIRED` to return for deactivated licenses.
## 2.9.2 (2017-08-28)
### Fixed
* A major bug causing `LA_FAIL` status to be returned for activated products.
## 2.9.0 (2017-07-03)
### Added
* clang build for macOS.
### Updated
* `ActivateProduct()` function now returns (throws) `LA_E_ACT_LIMIT` error (exception) if activation limit is reached.
* `IsProductGenuine()` function won't reactivate the product key, if deactivated server side.
## 2.8.1 (2017-05-21)
### Fixed
* Embedded version.
## 2.8.0 (2017-05-16)
### Added
* Support for changing product version without restart.
### Fixed
* Minor bug fixes.
## 2.7.1 (2017-04-05)
### Fixed
* GCE VM detection bug.
## 2.7.0 (2017-03-04)
### Added
* Support for Linux ARMv5 and ARMv7 architectures.
* Server sync for revoked licenses.
### Fixed
* Minor bug fixes.
## 2.6.1 (2017-01-26)
### Fixed
* A memory leak in `IsProductGenuine()` function if being invoked periodically.
## 2.6.0 (2017-01-22)
### Updated
* `DeactivateProduct()` now returns `LA_E_DEACT_LIMIT` instead of `LA_FAIL` if deactivation limit is reached for the key.
### Fixed
* Minor bug fixes.
## 2.5.1 (2016-12-27)
### Updated
* All setter functions other than `SetVersionGUID()` are now only needed at the time of activation.
* `DeactivateProduct()` now deactivates the product even if product key is expired.
### Fixed
* AWS VM detection bug.
## 2.4.0 (2016-12-12)
### Added
* `SetUserLock()` function to support user locked licenses.
### Updated
* `DeactivateProduct()` function now deactivates the product locally even if product key is already deactivated server side, and `LA_FAIL` is returned.
## 2.3.0 (2016-05-22)
### Fixed
* A minor bug in offline activation.
* A minor bug in VM activation.
## 2.2.1 (2016-03-21)
### Added
* `GetExtraActivationData()` function to get the value of the extra activation data.
* `GetDaysLeftToExpiration()` function to get the number of remaining days after which the license expires.
---
# LexFloatClient
Section: Changelogs
URL: https://cryptlex.com/docs/changelogs/lexfloatclient
Summary: Changelog for the LexFloatClient SDK, covering new functions, platform support, deprecations, and fixes in each version.
Last updated: 2026-07-15
## 4.16.1 (2026-07-15)
### Updated
* Updated the cryptographic algorithms used to protect data exchanged with LexFloatServer to a stronger scheme.
## 4.16.0 (2026-04-21)
### Added
* Added support for 16 KB page sizes in LexFloatClient for Android.
## 4.15.0 (2026-03-26)
### Added
* `baseValue` property added to the `HostFeatureEntitlement` object returned by `GetHostFeatureEntitlement()`.
## 4.14.0 (2026-03-24)
### Added
* `GetHostLicenseEntitlementSetTier()` function returns the tier of the entitlement set associated with the LexFloatServer license.
### Updated
* `RequestOfflineFloatingLicense()` now returns `LF_E_LEASE_EXCEEDS_SERVER_LICENSE_EXPIRY` when the requested lease exceeds the LexFloatServer license expiry.
### Fixed
* Minor bug fixes.
## 4.13.1 (2026-02-27)
### Updated
* Improved host URL validation.
## 4.13.0 (2026-01-02)
### Added
* `expiresAt` property added to the `HostFeatureEntitlement` object returned by `GetHostFeatureEntitlement()`.
### Fixed
* Resolved an issue affecting offline license restoration on Windows when `LF_ALL_USERS` was used.
## 4.12.0 (2025-08-05)
### Added
* `GetHostProductMetadata()` function returns the value of the product metadata.
### Updated
* `libcurl` version has been updated to v8.14.1.
## 4.11.0 (2025-05-22)
### Added
* `GetHostLicenseEntitlementSetName()` function returns the name of the entitlement set associated with the LexFloatServer license.
* `GetHostLicenseEntitlementSetDisplayName()` function returns the display name of the entitlement set associated with the LexFloatServer license.
* `GetHostFeatureEntitlements()` function returns the list of feature entitlements associated with the LexFloatServer license.
* `GetHostFeatureEntitlement()` function returns a specific feature entitlement associated with the LexFloatServer license.
### Updated
* Moved `HostConfig` struct to LexFloatClientTypes.h.
### Fixed
* Addressed crashing issue in multi threaded applications.
### Deprecated
* `GetHostProductVersionName()` function has been deprecated in favour of `GetHostLicenseEntitlementSetName()` function.
* `GetHostProductVersionDisplayName()` function has been deprecated in favour of `GetHostLicenseEntitlementSetDisplayName()` function.
* `GetHostProductVersionFeatureFlag()` has been deprecated in favour of `GetHostFeatureEntitlement()` function.
## 4.10.0 (2024-12-02)
### Added
* Support for Windows ARM64 builds.
## 4.9.2 (2024-11-14)
### Fixed
* Minor bug fix.
## 4.9.1 (2024-10-30)
### Updated
* Signed builds for macOS.
## 4.9.0 (2024-08-05)
### Added
* `GetFloatingClientMetadata()`, `RequestOfflineFloatingLicense()`, `GetFloatingLicenseMode()`, `GetFloatingClientLeaseExpiryDate()`, `GetHostConfig()`, `SetPermissionFlag()` API functions.
### Updated
* Updated the data type of `allowedUses` to `int64_t`, `totalUses` to `uint64_t` and `grossUses` to `uint64_t` of `GetHostLicenseMeterAttribute()` function.
## 4.8.1 (2024-05-15)
### Updated
* Included SSL support for secure communications.
## 4.8.0 (2023-12-01)
### Added
* `GetFloatingClientLibraryVersion()` API function.
## 4.7.7 (2023-09-23)
### Fixed
* Minor bug fix.
## 4.7.6 (2023-09-21)
### Updated
* Increased default network timeout to 60 secs.
## 4.7.5 (2023-04-10)
### Fixed
* Minor bug fix.
## 4.7.4 (2022-12-05)
### Fixed
* Encoding issues in feature related functions.
## 4.7.3 (2022-10-19)
### Fixed
* Added missing digital signature for Windows DLLs.
## 4.7.2 (2022-08-10)
### Fixed
* Removed external `libcurl` dependency in Linux `musl` build.
## 4.7.1 (2022-04-12)
### Fixed
* Issue with the function name.
## 4.7.0 (2022-04-11)
### Added
* `GetHostProductVersionName()`, `GetHostProductVersionDisplayName()` and `GetHostProductVersionFeatureFlag()` API functions.
## 4.6.0 (2021-07-14)
### Added
* Support for Android and iOS.
## 4.5.3 (2021-05-06)
### Updated
* Updated networking library for Windows.
## 4.5.2 (2021-04-22)
### Updated
* Dropped dependency on `libnss3` for Linux.
## 4.5.1 (2021-04-06)
### Fixed
* Fixed a minor security issue.
## 4.5.0 (2021-03-23)
### Added
* Support for getting `grossUses` of meter attributes.
## 4.4.3 (2021-02-25)
### Fixed
* Intermittent crashes in multi-threaded usage.
## 4.3.2 (2020-01-30)
### Fixed
* Minor bug fixes.
## 4.3.1 (2019-11-19)
### Fixed
* Minor bug fixes.
## 4.1.0 (2019-07-02)
### Added
* `GetHostLicenseMeterAttribute()`, `GetFloatingClientMeterAttributeUses()`, `IncrementFloatingClientMeterAttributeUses()`, `DecrementFloatingClientMeterAttributeUses()` and `ResetFloatingClientMeterAttributeUses()` API functions.
## 4.0.0 (2018-12-17)
### Added
* `SetFloatingClientMetadata()` and `GetHostLicenseExpiryDate()` API functions.
### Updated
* All status codes have been updated.
* Header file and samples for all languages on Github have been updated.
* Renamed `GetHandle()` function to `SetHostProductId()`.
* Renamed `SetFloatingServer()` function to `SetHostUrl()`.
* Renamed `SetLicenseCallback()` function to `SetFloatingLicenseCallback()`.
* Renamed `GetLicenseMetadata()` function to `GetHostLicenseMetadata()`.
* Renamed `RequestLicense()` function to `RequestFloatingLicense()`.
* Renamed `DropLicense()` function to `DropFloatingLicense()`.
* Renamed `HasLicense()` function to `HasFloatingLicense()`.
### Deleted
* `FindHandle()` function.
* `GlobalCleanup()` function.
## 3.0.0 (2018-05-03)
### Updated
* All status codes have been updated.
* Renamed `SetVersionGUID()` function to `SetProductId()`.
* Renamed `GetCustomField()` function to `GetLicenseMetadata()`.
### Deleted
* `SetProductFile()` function.
## 2.9.0 (2017-07-03)
### Added
* clang build for macOS.
---
# LexFloatServer
Section: Changelogs
URL: https://cryptlex.com/docs/changelogs/lexfloatserver
Summary: Changelog for LexFloatServer, covering new endpoints, configuration parameters, and fixes in each version.
Last updated: 2026-08-14
## 4.22.0 (2026-08-14)
### Added
* Added support for sandboxed environments.
## 4.21.1 (2026-07-15)
### Updated
* Updated the cryptographic algorithms used to protect data exchanged between LexFloatServer and connecting clients to a stronger scheme.
* Updated LexActivator version to v3.42.2.
### Fixed
* Fixed a security vulnerability affecting offline license activation. Upgrading is strongly recommended.
## 4.21.0 (2026-04-23)
### Added
* Added crypto-binding support for Windows.
## 4.20.1 (2026-03-31)
### Fixed
* Minor bug fix.
## 4.20.0 (2026-03-26)
### Added
* Added `baseValue` property to the `FeatureEntitlement` object.
## 4.19.0 (2026-03-24)
### Updated
* Updated LexActivator version to v3.39.1.
## 4.18.1 (2026-03-10)
### Updated
* Updated LexActivator version.
## 4.18.0 (2026-01-02)
### Added
* Added `expiresAt` property to the `FeatureEntitlement` object.
### Updated
* Updated LexActivator version.
* Enabled license reactivation directly from the LexFloatServer dashboard without requiring prior deactivation.
### Fixed
* Minor bug fixes.
## 4.17.0 (2025-12-03)
### Updated
* Updated LexActivator version.
## 4.16.1 (2025-11-17)
### Fixed
* Minor bug fix.
## 4.16.0 (2025-10-21)
### Updated
* Updated LexActivator version.
## 4.15.2 (2025-09-24)
### Updated
* Updated LexActivator version.
## 4.15.1 (2025-09-04)
### Updated
* Updated LexActivator version.
## 4.15.0 (2025-09-02)
### Added
* Improved device fingerprinting algorithm on Linux for improved reliability.
## 4.14.5 (2025-08-13)
### Fixed
* Minor bug fix.
## 4.14.4 (2025-08-05)
### Updated
* LexActivator version to v3.33.0.
## 4.14.3 (2025-05-28)
### Updated
* LexActivator version to v3.32.3.
## 4.14.2 (2025-05-27)
### Updated
* LexActivator version to v3.32.2.
## 4.14.1 (2025-05-27)
### Updated
* LexActivator version to v3.32.1.
## 4.14.0 (2025-05-22)
### Added
* `/api/server/feature-entitlements` endpoint to get the list of feature entitlements associated with the LexFloatServer.
### Updated
* Windows build of LexFloatServer is now distributed as two separate files (LexFloatServer.exe and LexActivator.dll) instead of a single unified executable to address crash issues.
* LexActivator version to v3.32.0.
## 4.13.4 (2025-03-18)
### Updated
* LexActivator version to v3.31.3.
## 4.13.3 (2024-11-14)
### Updated
* LexActivator version to v3.30.2.
## 4.13.2 (2024-10-30)
### Updated
* Signed builds for macOS.
* Updated minimum Windows OS requirement to Windows 10.
### Fixed
* Bug fixes.
## 4.13.1 (2024-09-19)
### Updated
* The dashboard is now served at `/` path instead of `/app` path. Requests to `/app` are redirected to `/` for backward compatibility.
## 4.13.0 (2024-08-05)
### Added
* `maxOfflineLeaseDuration` config file param to set the maximum duration in seconds that an offline license lease can last.
* `allowedOfflineFloatingClients` config file param to set the maximum number of clients that can simultaneously hold an offline license lease.
* `/api/server/config` public endpoint to get the value of the properties set in the `config.yml`.
* `maxOfflineLeaseDuration`, `allowedOfflineFloatingClients`, `totalOfflineFloatingClients` properties added to `/api/server/stats` endpoint.
* LexFloatServer now supports listing the trusted proxies via the `config.yml` file.
### Updated
* Logging of floating licenses that were not gracefully dropped (zombie licenses).
* LexActivator version to v3.29.0.
* `/api/server/stats` endpoint's `totalLicense` property has been renamed to `allowedFloatingClient`.
* `/api/server/stats` endpoint's `availableLicense` property has been renamed to `totalLicenses`.
## 4.12.0 (2024-05-14)
### Added
* LexFloatServer now supports enabling SSL through the `config.yml` file.
### Fixed
* LexFloatServer now updates license expiry date automatically after activation or server sync without requiring a restart.
## 4.11.2 (2023-12-22)
### Fixed
* Minor bug fixes.
## 4.11.1 (2023-12-14)
### Updated
* LexActivator version to v3.25.0.
## 4.11.0 (2023-12-07)
### Added
* `enableIpv6` config file param to enable LexFloatServer to serve requests over IPv6.
### Fixed
* `productFilePath` config file param now takes an absolute path as well.
## 4.10.0 (2023-11-09)
### Added
* `/api/server/license-meter-attributes` endpoint to get the meter attributes associated with the license.
### Updated
* Improved meter attribute logs.
### Fixed
* Minor bug fixes.
## 4.9.5 (2023-09-21)
### Updated
* LexActivator version to v3.24.1.
## 4.9.4 (2023-08-11)
### Fixed
* Added missing WMI service error log.
* Enforced service startup type to auto-delayed (Windows).
### Updated
* LexActivator version to v3.23.0.
## 4.9.3 (2023-06-24)
### Fixed
* Minor bug fix.
## 4.9.2 (2023-06-03)
### Fixed
* Issues related to service uninstallation on Windows.
### Updated
* LexActivator version to v3.21.4.
## 4.9.1 (2023-05-05)
### Fixed
* Minor bug fixes.
## 4.9.0 (2023-04-04)
### Added
* `/api/server/license-info` endpoint to get the information related to the license used to activate the LexFloatServer.
### Fixed
* Issue related to the service path on Linux.
## 4.8.10 (2023-02-10)
### Fixed
* False positive container detection on some Linux distributions.
## 4.8.9 (2023-02-10)
### Fixed
* Container detection issue on recent Linux distributions.
## 4.8.8 (2022-12-01)
### Updated
* LexActivator version to v3.20.7.
## 4.8.7 (2022-11-03)
### Updated
* LexActivator version to v3.20.2.
## 4.8.6 (2022-10-31)
### Fixed
* Added missing digital signature in case of Windows.
## 4.8.5 (2022-07-26)
### Updated
* Improved error logs.
## 4.8.4 (2022-07-05)
### Updated
* Allow activation if the server is already activated.
## 4.8.3 (2022-07-01)
### Fixed
* Added missing error return codes.
## 4.8.2 (2022-06-20)
### Updated
* LexActivator version to v3.19.1.
## 4.8.1 (2022-06-15)
### Updated
* Support for the new product.dat file.
## 4.8.0 (2022-04-06)
### Added
* Support for the feature flags.
## 4.7.0 (2021-12-08)
### Updated
* Improved logging.
### Fixed
* Issues related to meter attributes when the license is activated through the dashboard.
## 4.6.8 (2021-08-11)
### Fixed
* Incorrect exit return codes.
## 4.6.7 (2021-08-11)
### Fixed
* Minor bug fixes.
## 4.6.6 (2021-08-03)
### Fixed
* Minor bug fixes.
## 4.6.5 (2021-07-15)
### Updated
* Minor performance improvements.
## 4.6.4 (2021-07-08)
### Fixed
* Issue related to log folder path.
## 4.6.3 (2021-06-15)
### Fixed
* Issues related to incrementing of meter attributes.
* Issue related to incorrect encoding.
## 4.6.2 (2021-06-15)
### Fixed
* Issue causing server activation to disappear on restart in Windows.
## 4.6.1 (2021-06-15)
### Fixed
* Minor bug fixes.
## 4.6.0 (2021-06-14)
### Added
* Multi-threading support so it can now be vertically scaled to handle thousands of clients.
* Dashboard wherein you can login, view active floating licenses, activate/deactivate the LexFloatServer etc.
* Improved logging and colored console logs are supported too on Linux and macOS.
* Support for running as a service on Linux without writing any systemd or init script.
### Updated
* Command-line options are now posix-compliant. Please check the updated options using lexfloatserver --help command.
* YAML based config file and by default lexfloatserver looks for config.yml file in the same directory as lexfloatserver, so you don't need to pass the config file path.
## 4.5.3 (2021-05-06)
### Updated
* Updated networking library for Windows.
## 4.5.2 (2021-04-22)
### Updated
* Dropped dependency on `libnss3` for Linux.
## 4.5.1 (2021-04-06)
### Fixed
* Minor bug fix.
## 4.5.0 (2021-03-23)
### Added
* Support for persistent meter attributes (non-floating).
* Support for offline syncing of meter attributes (non-floating) during offline activation.
## 4.4.3 (2021-02-25)
### Fixed
* Some performance-related issues.
## 4.4.2 (2021-02-08)
### Fixed
* Issue causing offline activation to fail when the number of meter attributes is very large.
## 4.4.1 (2021-01-18)
### Fixed
* Buffer overflow issues causing activation verification to fail.
## 4.4.0 (2021-01-11)
### Added
* Support for running the server inside a container for testing purposes. The server must never be allowed to be run inside a container.
## 4.3.10 (2020-09-16)
### Added
* Support for bypassing system proxy settings. Just add `api.cryptlex.com` to the bypass proxy hosts list in the system proxy settings.
## 4.3.8 (2020-08-18)
### Fixed
* Bug causing the cache to return incorrect status code.
## 4.3.7 (2020-06-12)
### Fixed
* Minor bug fixes.
## 4.3.6 (2020-06-01)
### Added
* Improved device fingerprinting of devices running Linux.
## 4.3.5 (2020-04-14)
### Fixed
* Bug preventing the detection of Hyper-V on some Windows 10 machines.
## 4.3.4 (2020-03-20)
### Fixed
* Minor bug fixes.
## 4.3.3 (2020-03-12)
### Fixed
* Minor bug fixes.
## 4.3.0 (2019-10-28)
### Added
* `dailylogrotation` config file param, so server logs roll over once they reach `maxSize` and only `maxBackups` rotated files are kept.
* New [/api/server/activate](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/overview), [/api/server/offline-activation-request](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/overview) and [/api/server/offline-activate](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/overview) endpoints.
## 4.2.0 (2019-07-23)
### Added
* `allowedclockoffset` config file param.
## 4.1.0 (2019-07-02)
### Added
* Support for meter attributes.
## 4.0.2 (2019-03-25)
### Added
* Support for detecting Dockers to prevent the running of LexFloatServer inside a Docker container.
## 4.0.1 (2019-02-24)
### Added
* New command line parameter `-cryptlexhost` to allow setting a custom host.
## 4.0.0 (2018-12-17)
### Added
* New [/api/floating-licenses](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/overview) endpoint to get the list of leased floating licenses.
* [Leasing strategy](https://cryptlex.com/docs/license-management/license-templates#leasing-strategy) can be set for the server to configure the behaviour of leasing floating licenses.
* [Lease duration](https://cryptlex.com/docs/license-management/license-templates#lease-duration) in the config can be overridden using `leaseDuration` property of license.
* Improved error and request logging.
* Server error codes like server license expired, suspended, grace period over etc. are now sent to clients too.
* `SetFloatingClientMetadata()` and `GetHostLicenseExpiryDate()` API functions.
### Updated
* Updated stats API endpoint, for details, check [docs](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/lexfloatserver-api-endpoints).
* The Minimum supported LexFloatClient version is `v4.0.0`.
## 3.0.2 (2018-09-10)
### Added
* Added activation and deactivation logs to the log file.
## 3.0.1 (2018-08-20)
### Fixed
* Fixed a bug preventing server from running as launchd daemon on macOS.
## 3.0.0 (2018-05-03)
### Added
* Command-line parameters `-metadatakey` & `-metadatavalue`.
### Updated
* Updated stats API endpoint, for details, check [docs](https://cryptlex.com/docs/sdks-and-apis/lexfloatserver/lexfloatserver-api-endpoints).
* Now uses `LexActivator` `v3.0.0` for license activation.
* Renamed command line parameter `-pkey` to `-licensekey`.
* Renamed command line parameter `-pfile` to `-productfile`.
* Renamed command line parameter `-orequest` to `-offlinerequest`.
* Renamed command line parameter `-oresponse` to `-offlineresponse`.
### Deleted
* Command-line parameter `-extradata`.
## 2.9.5 (2017-10-19)
### Fixed
* Bug causing grace period not to expire on no server sync.
## 2.9.4 (2017-09-23)
### Fixed
* Bug causing incorrect detection of Hyper-V.
## 2.9.3 (2017-09-09)
### Added
* `lastSyncedAt` and `gracePeriodStartAt` properties to stats API.
## 2.9.2 (2017-08-27)
### Fixed
* Major bug causing `LA_FAIL` status to be returned for activated server.
## 2.8.1 (2017-05-21)
### Fixed
* Embedded server version.
## 2.8.0 (2017-05-16)
### Added
* Support for changing product version without restart.
### Updated
* Disallowed leasing of licenses, if grace period is over and server is running.
### Fixed
* Fixed a time sync issue.
## 2.7.0 (2017-03-04)
### Added
* Support for running the server, in case server is not activated.
### Fixed
* A startup issue as service on Windows 7.
## 2.6.1 (2017-01-26)
### Fixed
* A memory leak issue.
## 2.6.0 (2017-01-22)
### Added
* `status` property to the stats api.
### Fixed
* Minor bug fixes.
## 2.5.1 (2016-12-27)
### Added
* Command-line parameter `-displayname` to update service name in Windows.
* Command-line parameter `-status` to display activation status details.
* Command-line parameters `-proxy`, `-graceperiod`, `-servercheckinterval` and `-extradata` which can only be passed at the time of activation.
* Support for multiple service instances.
### Deleted
* `Proxy`, `GracePeriod` and `ServerCheckInterval` from config file.
## 2.4.0 (2016-12-12)
### Added
* API endpoint to get the server stats: /services/api/stats.
* Client IP check to prevent VM snapshot floating clients.
## 2.3.0 (2016-05-22)
### Added
* Support for blocking IP addresses.
* Support for offline activations.