> For the complete documentation index, see [llms.txt](https://docs.bunny.com/guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bunny.com/guide/tour/license-key-management.md).

# License key management

If your software is distributed to end users or customers then you will need a **license key** system to allow activating the software and controlling which features are enabled.&#x20;

Every subscription in Bunny has an associated License key that can be validated to reveal the if the subscription is still active and what features or limits should be enabled.&#x20;

It supports both online and offline modes. Where the offline mode is useful for software or containers that do not have access to the internet.&#x20;

### Online mode

Online mode is the preferred approach because if there are changes to the features or entitlements of a subscription in Bunny these will be picked up when the license key is validated.&#x20;

To use online mode you will share the license key with end users who can set it as an environment variable in the distributed software.&#x20;

The **license key** is found by clicking on the Details link for a given subscription.

<figure><img src="/files/haePeKQ1afQETrFBvPsm" alt=""><figcaption></figcaption></figure>

The distributed software will perform the following steps:

* Make a call to Bunny licences/validate endpoint using the license key.&#x20;
* Verify the JWT that is returned
* Activate the software

{% hint style="warning" %}
The JWT returned will have a **1 hour** expiry.
{% endhint %}

### Offline mode

When the distributed software is air gapped or unable to connect to the internet a JWT can be generated either through the Bunny admin interface or by using the Bunny GraphQL API.&#x20;

To generate an offline JWT token, click on the subscription details and then select **Generate offline license** from the menu.&#x20;

<figure><img src="/files/kIXxCmPypLOGDVE6LcDx" alt=""><figcaption></figcaption></figure>

To generate the JWT via API see [offlineLicenseCreate](https://docs.bunny.com/developer/using-the-graphql-api/mutations/offlinelicensecreate) which will require submitting either the License Key or Subscription ID.&#x20;

{% hint style="warning" %}
The JWT returned will have a **1 year** expiry.&#x20;
{% endhint %}

### Validate license key

<mark style="color:green;">`POST`</mark> `https://auth.bunny.com/api/licenses/validate`

**Headers**

<table><thead><tr><th>Name</th><th width="374">Value</th></tr></thead><tbody><tr><td>Content-Type</td><td><code>application/json</code></td></tr><tr><td>Authorization</td><td><code>Bearer &#x3C;</code><strong><code>license_key</code></strong><code>></code></td></tr></tbody></table>

**Body**

| Name                  | Type   | Description                                                            |
| --------------------- | ------ | ---------------------------------------------------------------------- |
| instance\_fingerprint | string | Optional. Tracks a unique device identifier along wth the subscription |

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
  "token": "<SIGNED JWT>"
}
```

{% endtab %}

{% tab title="401" %}

```json
{
  "error": "License is not active"
}
```

{% endtab %}
{% endtabs %}

The final step is to verify the signature of the JWT and extract the subscription claim to get the entitlements.&#x20;

### Verify the JWT for authenticity&#x20;

Before the JWT can be trusted you should verify its signature, check the expiry date and also the issuer and audience claims.&#x20;

The issuer must be \`<https://auth.bunny.com\\`>

The audience must be 'bunny-license-key'

The JWT signature is verified using the public key hosted on the JWKs endpoint.&#x20;

```
https://auth.bunny.com/api/.well-known/jwks.json
```

When operating in offline mode the public keys at this endpoint should be downloaded and bundled with the distributed software.&#x20;

{% hint style="info" %}
The Bunny license SDK includes the JWKs for offline access and will use the JWKs endpoint for online access.&#x20;
{% endhint %}

Ask Claude or google how to verify a JWT using JWKs and you will be able to complete this final step.&#x20;

### Extract the subscription entitlements

Once the JWT signature is verified you can extract the subscription claim to get all of the details of the subscription.&#x20;

```json
{
  "iss": "https://auth.bunny.com",
  "aud": "bunny-license-key",
  "sub": "47946",
  "iat": 1779245995,
  "exp": 1810802947,
  "jti": "b82cd058-b877-433b-8d7d-b551000e377d",
  "subscription": {
    "id": 47946,
    "state": "active",
    "start_date": "2025-12-10",
    "end_date": "2026-12-09",
    "trial_start_date": null,
    "trial_end_date": null,
    "plan": {
      "code": "growth",
      "name": "Growth"
    },
    "price_list": {
      "code": "growth_annual",
      "name": "Growth Annual"
    },
    "features": [
      {
        "code": "users",
        "name": "users",
        "value": "",
        "quantity": 55
      },
      {
        "code": null,
        "name": "Base fee",
        "value": "",
        "quantity": 1
      }
    ]
  }
}
```

### SDK

To make this process easier use an official Bunny SDK which will take care of handling the workflow for both online and offline access.&#x20;

* [Rust SDK](https://crates.io/crates/bunnyapp-license) - Download from crates.io
* [Rust SDK source on Github](https://github.com/bunnyapp/bunny-license-rust)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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.bunny.com/guide/tour/license-key-management.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.
