# License Checks

License checks have a crucial role in the protection of your application.

This guide will explain online and offline license checks, their efficient organization within the application, and the implementation of a grace period.

## Prerequisites

Before proceeding, make sure you have completed the [**Getting Started (C++)**](/sdks/tutorials/getting-started/c++.md) or [**Getting Started (.NET/C#)**](/sdks/tutorials/getting-started/.net-c.md) tutorial and accomplished the following steps:

* Initialize **LicenseManager** (or **LicenseHandler**) with your configuration using the appropriate settings.
* Activate a license for your application.
* Implement the mechanism to retrieve the current license.

## Local Check

Local check does not require an Internet connection and performs the following actions:

{% stepper %}
{% step %}

### Verify license state

Verify if the license is enabled, active, and valid. If the license is not in a valid state, it will raise `LicenseStateException` in C++ or the following exceptions in .Net:

* `LicenseDeletedException`
* `LicenseDisabledException`
* `TrialLicenseExpiredException`
* `LicenseExpiredException`
* `LicenseInactiveException`
  {% endstep %}

{% step %}

### Confirm product match

Confirm if the license belongs to the configured product. If the product code of the license and configuration do not match, it will raise `ProductMismatchException`.
{% endstep %}

{% step %}

### Detect clock tampering

Detect cheating with the system clock. If cheating is detected, it will raise `ClockTamperedException` (C++) or `DateTimeCheatingException` (.Net).
{% endstep %}

{% step %}

### Ensure device binding

Ensure that the license belongs to the device. If the license doesn't belong to the device, it will raise `DeviceNotLicensedException`.
{% endstep %}

{% step %}

### VM detection

If VM detection is enabled, check if the device is a VM and if the license allows virtual machines. If VMs are not allowed and the application is running on a VM, it will raise `VMIsNotAllowedException`.
{% endstep %}

{% step %}

### Floating license timeout

For floating licenses, verify if the floating timeout has expired. If the timeout is expired, it will raise `FloatingTimeoutExpiredException`.
{% endstep %}
{% endstepper %}

To perform a local check, call the LocalCheck method:

{% tabs %}
{% tab title="C++" %}

```cpp
auto license = licenseManager->getCurrentLicense();
license->localCheck();
```

{% endtab %}

{% tab title="C#" %}

```csharp
var license = licenseManager.CurrentLicense();
license.LocalCheck();
```

{% endtab %}

{% tab title="Swift" %}

```swift
try license.localCheck()
```

{% endtab %}

{% tab title="Python" %}

```python
manager = LicenseManager(conf)

license = manager.load_license()

license.local_check()
```

{% endtab %}

{% tab title="Go" %}

```go
	// Go SDK v2
	license_data, check_resp, err := lh.LocalCheck(true)
```

{% endtab %}

{% tab title="Java" %}

```java
License license = licenseManager.getCurrent();
license.localCheck();
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const license = licenseManager.loadLicense();
license.localCheck().then(response => {
  console.log('ok');
}).catch(error => {
  console.error(error);
});
```

{% endtab %}
{% endtabs %}

## Online Check

* Verify if the license is enabled, active, and valid. If the license is not in a valid state, it will raise `LicenseStateException` in C++ or the following exceptions in .Net:
  * `LicenseDeletedException`
  * `LicenseDisabledException`
  * `TrialLicenseExpiredException`
  * `LicenseExpiredException`
  * `LicenseInactiveException`
* Synchronize the consumption of consumption licenses and features. If there is not enough consumption left, it will raise `NotEnoughConsumptionException`.
* Update the license with data from the license server.
* Retrieve the most recent installation file for the product.
* Register a floating license. If there are no floating slots available, it will raise `MaxFloatingReachedException`.

It can throw the exceptions related to connection issues: `NetworkException`, `NetworkTimeoutException`, and `LicenseServerException`. You can implement a grace period to allow using the application without connection to the server for a limited period.

To run the online check call Check method:

{% tabs %}
{% tab title="C++" %}

```cpp
license->check();
```

{% endtab %}

{% tab title="C#" %}

```csharp
license.Check();
```

{% endtab %}

{% tab title="Java" %}

```java
licenseManager.checkLicense(license);
```

{% endtab %}

{% tab title="Swift" %}

```swift
try license.fullCheck()
```

{% endtab %}

{% tab title="Python" %}

```python
license.check()
```

{% endtab %}

{% tab title="Go" %}

```go
	// Go SDK v2
	license_data, err = lh.CheckLicense(ctx)
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const license = licenseManager.loadLicense();
license.check().then(response => {
  console.log('ok');
}).catch(error => {
  console.error(error);
});
```

{% endtab %}
{% endtabs %}

## License Check Optimization

License checks can take up to a couple of seconds. It is recommended to run them in a background thread.

Perform local checks on every application startup to ensure the user has a valid license.

However, since calling an online check at every start of the application is redundant, we recommend performing it every few days, using the last check date value saved in the license.

{% tabs %}
{% tab title="C++" %}

```cpp
if(license->daysPassedSinceLastCheck() >= 3)
  license->check();
```

{% endtab %}

{% tab title="C#" %}

```csharp
if( license.DaysPassedSinceLastCheck() >= 3 )
  license.Check();
```

{% endtab %}

{% tab title="Swift" %}

```swift
if Date().timeIntervalSince(linense.lastSyncDate) > 24 * 60 * 60 { // 1 day.
    try license.fullCheck()
}
```

{% endtab %}

{% tab title="Python" %}

```python
if license.days_since_last_check() >= 3:
    license.check()
```

{% endtab %}

{% tab title="Java" %}

```java
long daysPassedSinceLastCheck = license.daysPassedSinceLastCheck();
if (daysPassedSinceLastCheck > 3) {
    licenseManager.checkLicense(license);
}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const license = licenseManager.loadLicense();
if (license.daysSinceLastCheck > 3) {
  license.check().then(response => {
    console.log('ok');
  }).catch(error => {
    console.error(error);
  });
}
```

{% endtab %}
{% endtabs %}

If you need to synchronize consumption more often, you can use `SyncConsumption` and `SyncFeatureConsumption` methods.

## Grace Period

A grace period can be helpful when you don't want to restrict application usage due to online check failures caused by the lack of an internet connection or internal LicenseSpring server issues.

To implement this, define how long it is allowed to use the application without connecting to the server and handle network exceptions accordingly.

{% tabs %}
{% tab title="C++" %}

```cpp
auto allowedPeriodWithoutCheck = 7;//allow a week of usage without connection
try
{
  license->check();
  return true; //continue after successful check
}
catch( const LicenseSpringException& ex )
{
  auto code = ex.getCode();
  if(code == eNoInternetError || code == eNetworkTimeoutError || code == eServerError)
    return license->daysPassedSinceLastCheck() < allowedPeriodWithoutCheck;
    //stop if the app is offline or cannot connect to the server longer than the allowed period
  return false;//stop in case of other exceptions
}
```

{% endtab %}

{% tab title="C#" %}

```csharp
var allowedPeriodWithoutCheck = 7;//allow a week of usage without connection
try
{
  license.Check();
  return true;//continue after successful check
}
catch( LicenseSpringException ex )
{
  if( ex is NetworkException || ex is LicenseServerException )
    return license.DaysPassedSinceLastCheck() < allowedPeriodWithoutCheck;
    //stop if the app is offline or cannot connect to the server longer than the allowed period
  return false;//stop in case of other exceptions
}
```

{% endtab %}

{% tab title="Java" %}

```java
LicenseSpringConfiguration config = 
    LicenseSpringConfiguration.builder()
        .gracePeriodDays(3) // 3 days of grace period
        .build();
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const licenseManager = new LicenseManager({
  apiPath: 'string',
  publicKey: 'string',
  appName: 'string',
  appVersion: 'string',
  filePath: 'string',
  filename: 'string',
  fileKey: 'string',
  apiKey: 'string',
  sharedKey: 'string',
  productCode: 'string',
  gracePeriod: 3
});
```

{% endtab %}
{% endtabs %}

The grace period feature is available in **C++ SDK** from **v7.26.0** and in **.Net SDK** from **v7.22.0**. It covers `License::check`, `License::syncConsumption`, `License::syncFeatureConsumption`, and `License::sendDeviceVariables` methods.

{% hint style="warning" %}
Do not confuse grace period and subscription grace period. To learn more about the subscription grace period, see: [**Time Limited vs Subscription Licenses**](/license-entitlements/license-types/time-limited-vs-subscription-licenses.md)
{% endhint %}

By default grace period is **48 hours**. You can set another value using:

{% tabs %}
{% tab title="C++" %}

```cpp
LicenseSpring::ExtendedOptions options;
options.setGracePeriod(24);//set 24 hours
options.setGracePeriod(0);//disable grace period
```

{% endtab %}

{% tab title="C#" %}

```csharp
var options = new LicenseSpring.ExtendedOptions();
options.GracePeriod = 24;//set 24 hours
options.GracePeriod = 0;//disable grace period
```

{% endtab %}

{% tab title="Python" %}

```python
conf = Configuration(product="your_product_key",api_key="your_api_key",
                   shared_key="your_shared_key",file_key=key,file_iv=iv,
                   grace_period_conf=24)
       
```

{% endtab %}

{% tab title="Go" %}

```go
// Go SDK v2
lm_config := license_manager.LicenseManagerBasicConfiguration{
				OAuth:             false,
				ApiKey:            "your-api-key",
				SharedKey:         "your-shared-key",
				ProductCode:       "your-product-code",
				AuthData:          auth.FromKey("LICENSE-KEY"),
			}

lm, _ := license_manager.NewLicenseManager(
    lm_config,
    license_manager.WithGracePeriod(24),
)

cfg.Manager = lm

lh, _ := license_handler.NewLicenseHandler(cfg)
```

{% endtab %}

{% tab title="Java" %}

```java
// gracePeriodDays default value is 0
LicenseSpringConfiguration config = 
    LicenseSpringConfiguration.builder()
        .gracePeriodDays(3) // 3 days of grace period
        .build();
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const licenseManager = new LicenseManager({
  apiPath: 'string',
  publicKey: 'string',
  appName: 'string',
  appVersion: 'string',
  filePath: 'string',
  filename: 'string',
  fileKey: 'string',
  apiKey: 'string',
  sharedKey: 'string',
  productCode: 'string',
  gracePeriod: 3
});
```

{% endtab %}
{% endtabs %}

The `License` class has methods to check if the grace period started and get the grace period end date:

{% tabs %}
{% tab title="C++" %}

```cpp
license->check();
if(license->isGracePeriodStarted())
    std::cout << "Grace period started. " << license->gracePeriodHoursRemaining() << " hours till the end of grace period.";
```

{% endtab %}

{% tab title="C#" %}

```csharp
license.Check();
if( license.IsGracePeriodStarted() )
    Console.WriteLine( "Grace period started.{0} hours till the end of grace period.", license.GracePeriodHoursRemaining() );
```

{% endtab %}

{% tab title="Python" %}

```python
license.check()
if license.is_grace_period_started():
    print("Grace period hours remaining:",license.grace_period_hours_remaining())
```

{% endtab %}

{% tab title="Go" %}

```go
// Go SDK v2
if license_data.IsGracePeriodStarted():
    fmt.Println("Grace period started at: ",license_data.GracePeriodStartDate)
```

{% endtab %}

{% tab title="Java" %}

```java
LicenseSpringConfiguration config = 
    LicenseSpringConfiguration.builder()
        .gracePeriodDays(3) // 3 days of grace period
        .build();
   
// Grace period: ignore license check failures for 3 days after the last successful check     
long daysPassedSinceLastCheck = license.daysPassedSinceLastCheck();
```

{% endtab %}
{% endtabs %}

The grace period starts when one of the covered requests fails and resets after a successful request. The license is currently in its grace period if either it is a non-floating license, or it is a floating license with at least one hour remaining before expiration.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.licensespring.com/sdks/tutorials/best-practices/license-checks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
