# License Features

Software vendors frequently need the capability to independently manage entitlements for distinct components or modules within their primary application.

LicenseSpring accomplishes this through its advanced licensing features. It offers two types of feature licensing: consumption-based and activation-based.

This tutorial will explore the effective utilization of license features within your application.

{% embed url="<https://www.youtube.com/watch?v=2T1yclpXjyA&ab_channel=LicenseSpringSoftware>" %}

{% stepper %}
{% step %}

### Prerequisites

Completed the Getting Started tutorials, specifically:

* Initialized LicenseManager (or LicenseHandler) with your configuration using the appropriate settings.
* Activated a license.
  {% endstep %}
  {% endstepper %}

### Types of License Features

* Activation features are straightforward, operating as either enabled or disabled based on a license.
* Consumption features offer more complexity, featuring a "Maximum Consumptions" parameter that increments the "Total Consumptions" count whenever a user utilizes the feature. Additionally, you have the flexibility to establish overage settings for individual product features and specify a period for resetting consumptions.

### Adding License Features

License features can be added on the LicenseSpring platform, on the product page under "Features".

![Adding Product Feature](/files/10ab6a19878cc4d2294dc0d76228824258f76c92)

See [**Product Features**](/product-configuration/product-features.md) for a more in-depth look at adding license features.

### Accessing License Features

There are two ways of retrieving license features:

* Retrieving a product (license) feature by feature code.
* Retrieving all product features available for the license.

First, to access a specific license feature within the SDKs, the following method can be used:

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

```cpp
license->feature("feature_code");
```

{% endtab %}

{% tab title="C#" %}

```csharp
license.Feature( "feature_code" );
```

{% endtab %}

{% tab title="Swift" %}

```swift
if let feature = license.features.first(where: { $0.code == "feature_code" }) { ... }
```

{% endtab %}

{% tab title="Python" %}

```python
response = license.get_feature_data("feature_code") 

print(response)
```

{% endtab %}

{% tab title="Go" %}

```go
// Go SDK v2
license_data.GetFeature("feature code")
```

{% endtab %}

{% tab title="Java" %}

```java
License license = this.getCurrent();
LicenseData data = license.getData();
List<LicenseFeature> features = data.getProductFeatures();
```

{% endtab %}
{% endtabs %}

This method either returns a LicenseFeature object with the provided feature code, or throws an InvalidLicenseFeatureException if the feature code does not exist.

The other strategy includes receiving all available product features for a given license:

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

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

{% endtab %}

{% tab title="C#" %}

```csharp
license.Features();
```

{% endtab %}

{% tab title="Java" %}

```java
licenseData.getProductFeatures();
```

{% endtab %}

{% tab title="Swift" %}

```swift
let features = license.features
```

{% endtab %}

{% tab title="Python" %}

```python
features = license.features()

print(features)
```

{% endtab %}

{% tab title="Go" %}

```go
// Go SDK v2
license_data.FeatureManager.LicenseFeatures
```

{% endtab %}
{% endtabs %}

The `License::features()` method returns a `std::vector` of `LicenseFeature` objects in the C++ SDK and an array of `LicenseFeature` objects in the .NET SDK.

{% hint style="info" %}
Note: In the Java SDK, getProductFeatures() is called on a LicenseData object, not License.
{% endhint %}

### Consumption License Features

Consumption feature licensing enables measuring the usage of a feature within the application.

This is valuable when the vendor intends to restrict the frequency of specific functions being executed or reports being generated, among other scenarios.

To modify the usage levels of features, the following method is used:

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

```cpp
license->updateFeatureConsumption("feature_code", 1, true);
```

{% endtab %}

{% tab title="C#" %}

```csharp
license.UpdateFeatureConsumption( "feature_code", 1 );
```

{% endtab %}

{% tab title="Java" %}

```java
license.increaseFeatureConsumption( "product_code", 1 );
```

{% endtab %}

{% tab title="Swift" %}

```swift
try license.updateFeatureConsumption(code: "feature_code", difference: 2)
```

{% endtab %}

{% tab title="Python" %}

```python
license.add_local_feature_consumption("feature_code",1)
```

{% endtab %}

{% tab title="Go" %}

```go
// Go SDK v2
ld, err = license_handler.UpdateFeatureConsumption(featureCode, 1, true)
```

{% endtab %}
{% endtabs %}

The first parameter is the unique feature code associated with the feature under update, while the second parameter signifies the consumption value to be added. The last parameter determines whether the update is to be stored locally.

There are two options for measuring consumption on a device: local consumption and total consumption.

* Local consumption: consumptions are exclusively retrieved from the local license file, bypassing the backend. Useful for caching local consumption amounts per device to reduce API calls (LicenseSpring charges per API call). You can synchronize local consumption with the backend only when desired (e.g., program exit).
* Total consumption: encompasses both the total consumption on the LicenseSpring platform and the local consumption on the device. All users utilizing the same license will collectively share the consumption pool displayed on the platform.

When dealing with total consumption, developers utilize the following to synchronize feature consumption:

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

```cpp
license->syncFeatureConsumption("feature_code");
```

{% endtab %}

{% tab title="C#" %}

```csharp
license.SyncFeatureConsumption( "feature_code" );
```

{% endtab %}

{% tab title="Java" %}

```java
license.syncConsumptions()
```

{% endtab %}

{% tab title="Swift" %}

```swift
// Sync exact feature:
try license.syncFeatureConsumption(code: "feature_code")

// Sync all features:
try license.syncFeatureConsumption(code: nil)
```

{% endtab %}

{% tab title="Python" %}

```python
ld, err = license_handler.SyncFeatureConsumption(ctx, featureCode)
```

{% endtab %}

{% tab title="Go" %}

```go
// Go SDK v2
ld, err = license_handler.SyncFeatureConsumption(ctx, featureCode)
```

{% endtab %}
{% endtabs %}

It is advisable to call this method before trying to obtain the total consumption value and after updating the total consumption count.

If you are syncing properly, then your total consumption should be equal to your local consumption at any time.

{% hint style="info" %}
Note: To identify expired features, developers have the option to employ syncFeatureConsumption. In cases where a feature has been removed from the license, attempting to locate it using syncFeatureConsumption on the LicenseSpring platform will result in an InvalidLicenseFeatureException being thrown.
{% endhint %}

Identifying expired features can also be done through a license check with the includeExpiredFeatures parameter. In that case, the API returns a list of all non-expired and expired features:

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

```cpp
bool includeExpiredFeatures = true;
license->check(InstallFileFilter(), includeExpiredFeatures);
```

{% endtab %}

{% tab title="Python" %}

```python
response = license.check(include_expired_features=True)

print(response)
```

{% endtab %}
{% endtabs %}


---

# 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-features.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.
