# Download Release Source: https://docs.lukittu.com/api-reference/client--verify/download-release /api-reference/openapi.json get /api/v1/client/teams/{teamId}/verification/classloader The Classloader endpoint is used to download a release file. It is primarily intended for programming languages that support loading business logic code directly from a remote server into memory. For example, this is commonly used with Java classloaders. The downloaded file is encrypted using the session key provided in the request. The client must decrypt the file using the same session key. # License Heartbeat Source: https://docs.lukittu.com/api-reference/client--verify/license-heartbeat /api-reference/openapi.json post /api/v1/client/teams/{teamId}/verification/heartbeat The Heartbeat endpoint is used to determine whether a specific device is still active. You should call this endpoint at regular intervals (e.g., once every 30 minutes). This process also validates the license key in a similar way to the Verify License endpoint. # Verify License Source: https://docs.lukittu.com/api-reference/client--verify/verify-license /api-reference/openapi.json post /api/v1/client/teams/{teamId}/verification/verify This endpoint is used to validate a license key with the Lukittu backend. Typically, you should call this endpoint when your software starts and act based on the response provided. **Important Note**: If you are using a programming language that supports loading business logic code remotely (e.g., Java with a Remote ClassLoader), you should not use this endpoint. Instead, use the "classloader" endpoint for enhanced security. # Create Customer Source: https://docs.lukittu.com/api-reference/dev--customers/create-customer /api-reference/openapi.json post /api/v1/dev/teams/{teamId}/customers Create a new customer record for the specified team. Customers can be associated with licenses for tracking and management. # Delete Customer by ID Source: https://docs.lukittu.com/api-reference/dev--customers/delete-customer-by-id /api-reference/openapi.json delete /api/v1/dev/teams/{teamId}/customers/{customerId} Permanently delete a customer and all associated data including metadata and address information. **Warning**: This action cannot be undone. # Get Customer by ID Source: https://docs.lukittu.com/api-reference/dev--customers/get-customer-by-id /api-reference/openapi.json get /api/v1/dev/teams/{teamId}/customers/{customerId} Retrieve detailed information about a specific customer by their unique identifier. # List Customers Source: https://docs.lukittu.com/api-reference/dev--customers/list-customers /api-reference/openapi.json get /api/v1/dev/teams/{teamId}/customers Retrieve a paginated list of customers for the specified team. Supports search, pagination, and sorting capabilities. # Update Customer Source: https://docs.lukittu.com/api-reference/dev--customers/update-customer /api-reference/openapi.json put /api/v1/dev/teams/{teamId}/customers/{customerId} Update an existing customer's information including email, name, metadata, and address. # Create License Source: https://docs.lukittu.com/api-reference/dev--licenses/create-license /api-reference/openapi.json post /api/v1/dev/teams/{teamId}/licenses Create a new license with the specified configuration. The license will be automatically generated with a unique key. # Delete License by ID Source: https://docs.lukittu.com/api-reference/dev--licenses/delete-license-by-id /api-reference/openapi.json delete /api/v1/dev/teams/{teamId}/licenses/id/{licenseId} Delete a license by its unique identifier. **This operation is permanent and cannot be undone.** # Delete License by Key Source: https://docs.lukittu.com/api-reference/dev--licenses/delete-license-by-key /api-reference/openapi.json delete /api/v1/dev/teams/{teamId}/licenses/{licenseKey} Delete a license by its license key. **This operation is permanent and cannot be undone.** # Get License by ID Source: https://docs.lukittu.com/api-reference/dev--licenses/get-license-by-id /api-reference/openapi.json get /api/v1/dev/teams/{teamId}/licenses/id/{licenseId} Retrieve a specific license by its unique identifier. # Get License by Key Source: https://docs.lukittu.com/api-reference/dev--licenses/get-license-by-key /api-reference/openapi.json get /api/v1/dev/teams/{teamId}/licenses/{licenseKey} Retrieve a specific license by its license key. # List License Hardware Identifiers Source: https://docs.lukittu.com/api-reference/dev--licenses/list-license-hardware-identifiers /api-reference/openapi.json get /api/v1/dev/teams/{teamId}/licenses/id/{licenseId}/hwid Retrieve a paginated list of hardware identifiers (HWIDs) associated with a specific license. Includes status calculation based on team timeout settings and filtering options. # List License IP Addresses Source: https://docs.lukittu.com/api-reference/dev--licenses/list-license-ip-addresses /api-reference/openapi.json get /api/v1/dev/teams/{teamId}/licenses/id/{licenseId}/ip-address Retrieve a paginated list of IP addresses associated with a specific license. Includes status calculation based on team timeout settings, country information, and filtering options. # List Licenses Source: https://docs.lukittu.com/api-reference/dev--licenses/list-licenses /api-reference/openapi.json get /api/v1/dev/teams/{teamId}/licenses Retrieve a paginated list of licenses for the specified team. Results can be filtered by product and customer associations. # Update Hardware Identifier Status Source: https://docs.lukittu.com/api-reference/dev--licenses/update-hardware-identifier-status /api-reference/openapi.json patch /api/v1/dev/teams/{teamId}/licenses/id/{licenseId}/hwid/{hwidId} Update the forgotten status of a hardware identifier. This allows you to "forget" (soft delete) or "remember" (restore) hardware identifiers. # Update IP Address Status Source: https://docs.lukittu.com/api-reference/dev--licenses/update-ip-address-status /api-reference/openapi.json patch /api/v1/dev/teams/{teamId}/licenses/id/{licenseId}/ip-address/{ipId} Update the forgotten status of an IP address. This allows you to "forget" (soft delete) or "remember" (restore) IP addresses. # Update License Source: https://docs.lukittu.com/api-reference/dev--licenses/update-license /api-reference/openapi.json put /api/v1/dev/teams/{teamId}/licenses/id/{licenseId} Update an existing license's properties including expiration, limits, metadata, associated products, and customers. Can also update the license key itself. # Create Release Source: https://docs.lukittu.com/api-reference/dev--releases/create-release /api-reference/openapi.json post /api/v1/dev/teams/{teamId}/releases Create a new release for a product. Supports optional file upload via multipart/form-data. The request body must be sent as `multipart/form-data` with: - `data` field (required): JSON string containing the release configuration - `file` field (optional): Binary file to attach to the release (max 10 MB) File uploads require the team to have the classloader feature enabled (paid subscription). # List Releases Source: https://docs.lukittu.com/api-reference/dev--releases/list-releases /api-reference/openapi.json get /api/v1/dev/teams/{teamId}/releases Retrieve a paginated list of releases for a specific product within the team. Results can be filtered by version search and release status. # Update Release Source: https://docs.lukittu.com/api-reference/dev--releases/update-release /api-reference/openapi.json put /api/v1/dev/teams/{teamId}/releases/{releaseId} Update an existing release. Supports optional file upload/replacement via multipart/form-data. The request body must be sent as `multipart/form-data` with: - `data` field (required): JSON string containing the release configuration - `file` field (optional): Binary file to attach to the release (max 10 MB) **File handling:** - To upload a new file (replacing any existing): include the `file` field - To keep the existing file unchanged: omit the `file` field and set `keepExistingFile` to `true` - To remove the existing file without uploading a new one: omit the `file` field and set `keepExistingFile` to `false` File uploads require the team to have the classloader feature enabled (paid subscription). # Get Team Statistics Source: https://docs.lukittu.com/api-reference/dev--statistics/get-team-statistics /api-reference/openapi.json get /api/v1/dev/teams/{teamId}/statistics Returns combined usage statistics for a team, including license counts, request metrics, top countries, top products, and recent activity. Results are cached for 15 minutes per team. # Introduction Source: https://docs.lukittu.com/api-reference/introduction Overview of the Lukittu API documentation, including endpoints, request and response formats, parameters, and examples. Welcome to the Lukittu API documentation. Here you will find detailed information about the various endpoints available, including their request and response formats, parameters, and examples. Whether you are verifying licenses, sending heartbeats, or loading classes, our API provides the necessary endpoints to accomplish these tasks efficiently. Explore the documentation to get started and learn more about how to use our API effectively. If you have any implementation issues, join our community server: [https://discord.lukittu.com](https://discord.lukittu.com). # Introduction Source: https://docs.lukittu.com/examples/introduction Here you can find premade code examples on how to implement Lukittu. # Advanced Source: https://docs.lukittu.com/examples/java/advanced # Advanced Classloader example The classloader is still a work in progress. Join our Discord and open a ticket, or send us an email at [support@lukittu.com](mailto:support@lukittu.com) for more information.\ If you are on the PRO plan, we will provide you access upon request. # Simple Source: https://docs.lukittu.com/examples/java/simple # Simple Java Example You can find a pre-made example plugin here: [lukittu-java-simple](https://github.com/KasperiP/lukittu-java-simple).\ This example demonstrates a robust implementation of the Lukittu license verification system for Java applications, specifically built as a Minecraft Bukkit/Spigot plugin. ## Features * **Secure License Verification**\ Implements a challenge-response mechanism with cryptographic signature verification using RSA/SHA256. * **Comprehensive Error Handling**\ Provides clear, user-friendly messages for various license states and error conditions. * **Heartbeat System**\ Periodically validates the license to ensure continued legitimacy. * **Device Identification**\ Generates a unique hardware-based identifier to limit installations per license. * **Security Best Practices**\ Includes documentation of proper security measures for production-level implementation. # Managed Hosting Source: https://docs.lukittu.com/hosting/managed-hosting Official managed hosting options for Lukittu, including free and Pro plans ## Overview Lukittu offers fully managed hosting solutions, eliminating the need to set up and maintain your own infrastructure. All managed hosting options are production-ready and include automatic updates, backups, and security patches. ## Available Plans * All essential features * Suitable for production use * Easily enough for majority of users! * €2.90/month or €32/year * Increased capacity * Access to Pro-only features * Priority support ## Pricing Philosophy Lukittu is not intended to generate profit. The Pro plan exists solely to help cover the operational costs of running the project, such as hosting infrastructure. ## Getting Started To get started with Lukittu's managed hosting: 1. Create an account on the [Lukittu platform](https://lukittu.com) 2. Set up your team and products 3. Begin creating licenses immediately The free tier is automatically applied to new accounts with no credit card required. # Self-hosting Source: https://docs.lukittu.com/hosting/self-hosting Information about self-hosting options and considerations for the Lukittu platform ## Current Status As of May 7, 2025, Lukittu does not provide any official self-hosting guides or support. Lukittu offers free managed hosting for all users with a generous free tier. Before considering self-hosting, you might want to check out the [Managed Hosting](/hosting/managed-hosting) option. ## Why No Self-hosting? Lukittu was originally designed as a SaaS solution, not as a self-hosted, single-tenant application. The platform makes several architectural assumptions: * **Multi-tenant environment** where anyone can register * Users can create their own teams * Shared database and infrastructure ## Third-Party Service Dependencies Lukittu uses third-party services that are tightly coupled with the application code: * Sentry for error monitoring * Stripe for subscription management * Proxy/CDN (Cloudflare) configuration * Other external services These integrations weren't designed to be optional or easily replaceable in a self-hosted scenario. ## Self-hosting Considerations Self-hosting Lukittu is **not recommended** unless you have a strong understanding of its architecture and environment and you are aware of the drawbacks! ### Known Limitations * No support for single-tenant usage * No official documentation for self-hosting * Platform assumptions may lead to breaking changes in self-hosted setups * No dedicated support for self-hosted instances ## Summary The Lukittu platform was designed as a SaaS solution with multi-tenant architecture. While technically possible, self-hosting is not officially supported and comes with significant limitations and challenges. Consider these factors carefully before attempting to self-host Lukittu. If you need an open-source, single-tenant licensing system today, there are excellent alternatives available—such as [Keygen](https://github.com/keygen-sh/keygen-api?tab=readme-ov-file#self-hosting-with-keygen-ce). # BuiltByBit Integration Source: https://docs.lukittu.com/integrations/built-by-bit Lukittu supports BuiltByBit by providing a fully automatic licensing experience for your resources. # BuiltByBit Integration Lukittu automatically delivers licenses to your customers when they purchase through BuiltByBit. ## Implementation Overview Follow these steps to configure licensing for the products you sell using BuiltByBit: First, set up your product in the Lukittu platform. Activate the integration in your Lukittu dashboard. Configure BuiltByBit to notify Lukittu of purchase events. Set up automatic license delivery for your customers. ## Creating a Product in Lukittu Go to the **Products** page in your Lukittu dashboard and click **Add Product**. Enter a name for your product and click **Save**. Open the page for your newly created product and copy the product's **ID**. You'll need this ID when configuring your BuiltByBit webhook. ## Enabling BuiltByBit Integration Before setting up webhooks on BuiltByBit, you need to enable the integration in your Lukittu dashboard: Log in to your Lukittu dashboard and navigate to the **Integrations** tab. Locate the BuiltByBit integration option and toggle it to **Active**. Copy the generated **Secret** as you'll need it for the webhook setup. Keep this secret secure as it authenticates your webhook requests. ## Setting Up Purchase Webhook Follow these steps to configure the purchase webhook that will automatically issue licenses: Go to the [BuiltByBit webhooks dashboard](https://builtbybit.com/resources/dashboard/webhooks) and click the **Create webhook** button. Enter a descriptive name for the webhook. Select **Purchase** from the Trigger dropdown. Choose **Only apply to certain resources** and select the specific resource(s) you want to license. Enter the following URL: ``` https://app.lukittu.com/api/v1/integrations/built-by-bit?teamId=YOUR_TEAM_ID ``` Replace `YOUR_TEAM_ID` with your Lukittu team's ID. To find your Team ID, go to the Lukittu dashboard and navigate to **Team** → **Settings**. Select **Custom** for Template, **POST** for Method, and **application/json** for Content Type. Copy and paste the following JSON template: ```json theme={null} { "apiSecret": "YOUR_BUILT_BY_BIT_SECRET", "builtByBitData": { "user": { "id": "{user_id}", "username": "{username}", "userUrl": "{user_url}" }, "resource": { "title": "{resource_title}", "id": "{resource_id}", "url": "{resource_url}", "addon": { "id": "{addon_id}", "title": "{addon_title}" }, "bundle": { "id": "{bundle_id}", "title": "{bundle_title}" }, "renewal": "{renewal}", "pricing": { "listPrice": "{list_price}", "finalPrice": "{final_price}" }, "purchaseDate": "{purchase_date}" } }, "lukittuData": { "productId": "YOUR_LUKITTU_PRODUCT_ID", "ipLimit": null, "hwidLimit": null, "expirationDays": null, "expirationStart": null } } ``` Replace `YOUR_BUILT_BY_BIT_SECRET` with the integration secret from your Lukittu dashboard. Replace `YOUR_LUKITTU_PRODUCT_ID` with the product ID you copied earlier. The fields `ipLimit`, `hwidLimit`, `expirationDays`, and `expirationStart` are optional configuration parameters. Leave them as `null` if you don't need them, or set appropriate values based on your licensing requirements. Click the **Save** button to create your purchase webhook. ### Optional License Configuration The following parameters can be customized in the webhook JSON: | **Key** | **Type** | **Description** | | ----------------- | -------------------------- | :----------------------------------------------------------------------------------------------- | | `ipLimit` | Number | Maximum number of IPs allowed. | | `hwidLimit` | Number | Number of concurrent users allowed. | | `expirationDays` | Number | Number of days until the license expires. | | `expirationStart` | `ACTIVATION` or `CREATION` | Determines when expiration starts (default: `CREATION`). Applicable if `expirationDays` is used. | ## Setting Up License Placeholder To enable automatic license delivery to your customers, you need to create a license placeholder: Go to the [BuiltByBit placeholders page](https://builtbybit.com/placeholders/) and click the **Create placeholder** button. Enter a descriptive placeholder name (e.g., `%%__LUKITTU_LICENSE_KEY__%%`). Select **External license key** from the Type dropdown. Enter the following URL: ` https://app.lukittu.com/api/v1/integrations/built-by-bit/placeholder?teamId=YOUR_TEAM_ID ` Replace `YOUR_TEAM_ID` with your Lukittu team's ID. Enter the BuiltByBit integration secret you created on your Lukittu dashboard. Click the **Save** button to create your license placeholder. ## Manually Assigning BuiltByBit Licenses (Without a Purchase) In some cases, you may want to grant a BuiltByBit user access to one of your products even if they have not purchased it through BuiltByBit. Lukittu fully supports this by allowing you to manually attach the required BuiltByBit metadata to a license. When BuiltByBit processes a real purchase, it automatically sends the `BBB_USER_ID` and `BBB_RESOURCE_ID` values to Lukittu. If no purchase exists, you can add these values manually to any license you create. ### How It Works To manually link a license to a BuiltByBit user and resource: 1. Set the following metadata fields on the license: * **`BBB_USER_ID`** — The BuiltByBit user ID * **`BBB_RESOURCE_ID`** — The BuiltByBit resource ID 2. Once these metadata fields are present, **Lukittu treats the license exactly as if it were generated through a BuiltByBit purchase**. This means: * The license will correctly inject into BuiltByBit placeholders * All automation behaves normally ### Finding the Required IDs You can obtain both IDs directly from BuiltByBit URLs. #### Resource ID This is the numeric portion at the end of the resource URL: Example: `https://builtbybit.com/resources/lukittu-license-system-open-source.62494` Resource ID: **62494** #### User ID This is the numeric portion at the end of a user profile URL: Example: `https://builtbybit.com/members/kasperi.540773` User ID: **540773** ### Summary If you need to assign a license to a BuiltByBit user without a purchase, simply add `BBB_USER_ID` and `BBB_RESOURCE_ID` as metadata to the Lukittu license. Once added, the license will fully support BuiltByBit placeholder injection and behave identically to automatically issued licenses. ## Verifying the Integration * **Make a Test Purchase** - Make a test purchase of your resource on BuiltByBit. You can use a coupon to get it for free! - **Verify License Generation** - Check that a license is automatically generated in your Lukittu dashboard after the purchase. - **Confirm License Delivery** - Verify that the license key is correctly replacing the corresponding placeholder during download. # Discord Integration Source: https://docs.lukittu.com/integrations/discord Connect Lukittu to Discord for seamless license management through bot commands. # Discord Integration Lukittu's Discord integration allows you to manage licenses directly through Discord using bot commands. ## Setting Up Discord Integration Follow these steps to integrate Lukittu with Discord: Log in to your Lukittu dashboard and navigate to the **Integrations** tab. Find the Discord integration option and toggle it to **Active**. Go to your profile settings in the Lukittu dashboard and connect your Discord account. This step is required to establish the connection between your Lukittu account and Discord identity. Invite the Lukittu bot to your server or install it for personal use by clicking this link: [https://discord.com/oauth2/authorize?client\_id=1352929152134811679](https://discord.com/oauth2/authorize?client_id=1352929152134811679) You need appropriate permissions to add a bot to a Discord server. ## Discord Self-Verification Customers can verify directly on Discord using the `/verify ` command. Running `/verify` links Discord account to your Lukittu customer and automatically assigns all roles you are entitled to through the product’s role mapping. ### Requirements 1. The command must be executed within a Discord server (guild). 2. Your team must have Discord integration **enabled and active**. 3. The product associated with the license must have at least one role mapping configured for the guild where the command is run. ## Using the Discord Bot Once you've set up the integration, you can interact with the Lukittu bot on Discord: All messages exchanged with the Lukittu bot are ephemeral, meaning only you can see them. Other server members won't be able to view your license information or commands. ### Access Options When you add the bot to your Discord server, it becomes available to all members (with the appropriate permissions) within that server. If you choose the user installation option, you can use the bot's commands in any server or direct message, making it available for your personal use across Discord. # Polymart Integration Source: https://docs.lukittu.com/integrations/polymart Lukittu supports Polymart by providing a fully automatic licensing experience for your resources. # Polymart Integration Lukittu automatically delivers licenses to your customers when they purchase through Polymart. ## Implementation Overview Follow these steps to configure licensing for the products you sell using Polymart: First, set up your product in the Lukittu platform. Activate the integration in your Lukittu dashboard. Configure Polymart to notify Lukittu of purchase events. Set up automatic license delivery for your customers. ## Creating a Product in Lukittu Go to the **Products** page in your Lukittu dashboard and click **Add Product**. Enter a name for your product and click **Save**. Open the page for your newly created product and copy the product's **ID**. You'll need this ID when configuring your Polymart webhook. ## Enabling Polymart Integration Before setting up webhooks on Polymart, you need to enable the integration in your Lukittu dashboard: Log in to your Lukittu dashboard and navigate to the **Integrations** tab. Locate the Polymart integration option and toggle it to **Active**. The Polymart integration requires two secrets: - **Webhook Secret:** You'll get this after creating your webhook on Polymart. - **Signing Secret:** You'll get this when setting up the license placeholder. Both secrets are required for the integration to work properly. You'll add them after completing the webhook and placeholder setup in the following steps. ## Setting Up Purchase Webhook Follow these steps to configure the purchase webhook that will automatically issue licenses: Go to your product page on Polymart and click the **Webhooks** option. Click the **Add New Webhook** button to create a webhook for your product. Under "What events should your webhook receive?" select **Purchases**. Enter the following URL: ` https://app.lukittu.com/api/v1/integrations/polymart?teamId=YOUR_TEAM_ID&productId=YOUR_PRODUCT_ID ` Replace `YOUR_TEAM_ID` with your Lukittu team's ID and `YOUR_PRODUCT_ID` with the Lukittu product ID you copied earlier. To find your Team ID, go to the Lukittu dashboard and navigate to **Team** → **Settings**. Click the **Submit** button to save your webhook configuration. After submission, you'll receive a **webhook secret**. Copy the webhook secret provided by Polymart and paste it into the "Webhook Secret" field in the Polymart integration section of your Lukittu dashboard. ## Setting Up External License Placeholder To enable automatic license delivery to customers via placeholders, you need to set up a license placeholder in Polymart: Go to your product's edit page on Polymart and locate the **Security** section. In the Security section, select **External API** as your custom placeholder type. The "Key" field can be anything you want - it's just an identifier for Polymart. Enter the following URL in the API endpoint field: ` https://app.lukittu.com/api/v1/integrations/polymart/placeholder?teamId=YOUR_TEAM_ID ` Replace `YOUR_TEAM_ID` with your Lukittu team ID. To find your Team ID, go to the Lukittu dashboard and navigate to **Team** → **Settings**. At the bottom of the card, you'll find an **API signing secret**. Copy this secret value - you'll need to add it to Lukittu. Return to your Lukittu dashboard's Integrations section and paste the API signing secret into the **Signing Secret** field of the Polymart integration. ### Optional License Configuration The following query parameters can be added to your webhook URL to customize license properties: | **Parameter** | **Type** | **Description** | | ----------------- | -------------------------- | :----------------------------------------------------------------------------------------------- | | `ipLimit` | Number | Maximum number of IPs allowed (must be a positive integer). | | `hwidLimit` | Number | Number of concurrent users allowed (must be at least 1). | | `expirationDays` | Number | Number of days until the license expires (must be at least 1). | | `expirationStart` | `ACTIVATION` or `CREATION` | Determines when expiration starts (default: `CREATION`). Applicable if `expirationDays` is used. | Example URL with custom parameters: ``` https://app.lukittu.com/api/v1/integrations/polymart?teamId=YOUR_TEAM_ID&productId=YOUR_PRODUCT_ID&ipLimit=2&hwidLimit=1&expirationDays=30&expirationStart=CREATION ``` # Stripe Integration Source: https://docs.lukittu.com/integrations/stripe Lukittu supports Stripe by automatically delivering licenses to customers via email upon purchase. # Stripe Integration Lukittu automatically delivers licenses to your customers via email when they purchase through Stripe. ## Implementation Overview Follow these steps to configure licensing for the products you sell using Stripe: First, set up your product in the Lukittu platform. Configure an identical product in your Stripe dashboard. Connect your Stripe product to Lukittu using metadata fields. Configure Stripe to notify Lukittu of purchase events. Complete the integration by adding your Stripe API key and webhook secret. ## Creating a Product in Lukittu Go to the **Products** page in your Lukittu dashboard and click **Add Product**. Enter a name for your product and click **Save**. Open the page for your newly created product and copy the product's **ID**. You'll need this ID when configuring your Stripe product's metadata. ## Creating a Stripe Product for Lukittu Follow these steps to create and configure a Stripe product for use with Lukittu: Navigate to the **Product Catalog** section on your Stripe dashboard. Click the **Add a Product** button. Enter a product name. Use the same name as your Lukittu product for consistency and easier identification. Find the **More Options** dropdown. Open the dropdown and locate the **Metadata** section. Metadata allows you to add custom data to your Stripe product. Lukittu uses this metadata to map Stripe products to its backend. ### Required Metadata for Lukittu Add the following metadata key-value pairs to your product: | **Key** | **Description** | | ------------ | ------------------------------------------------------------------------------------------------ | | `product_id` | Your Lukittu product ID (required). Can be a single ID or a comma-separated list of product IDs. | ### Optional Metadata for Lukittu The following metadata keys are optional and can be added as needed: | **Key** | **Type** | **Description** | | ------------------ | -------------------------- | :------------------------------------------------------------------------------------------------ | | `ip_limit` | Number | Maximum number of IPs allowed. | | `hwid_limit` | Number | Number of concurrent users allowed. | | `expiration_days` | Number | Number of days until the license expires. | | `expiration_start` | `ACTIVATION` or `CREATION` | Determines when expiration starts (default: `CREATION`). Applicable if `expiration_days` is used. | ### Notes on Expiration and Subscriptions Do not use any expiration-related metadata (`expiration_days`, `expiration_start`). Lukittu automatically handles license expiration for subscription-based products. If a payment is not received, the license will expire automatically at the end of the billing period. Expiration metadata can be used as outlined above to define license durations. ## Adding a Stripe Webhook Use the search bar on your Stripe dashboard to search for **Webhooks**. Click **Add endpoint** to create a new webhook. Set the **Endpoint URL** to: ` https://app.lukittu.com/api/v1/integrations/stripe?teamId=YOUR_TEAM_ID ` Replace `YOUR_TEAM_ID` with your Lukittu team's ID. To find your Team ID, go to the Lukittu dashboard and navigate to **Team** → **Settings**. Select **Listen to events on your account**. Add the following events to the webhook: - `invoice.paid` - `customer.subscription.deleted` - `customer.subscription.created` - `customer.subscription.updated` - `checkout.session.completed` After configuring the events, save the newly created webhook. Once saved, Stripe will generate a **Signing Secret** for the webhook. The signing secret starts with `whsec_`. You will need this signing secret to complete the Stripe integration in Lukittu. ## Adding a Restricted API Key to Lukittu Go to the **API Keys** section on your Stripe dashboard. Click **Create Restricted Key**. In the dialog: - **Purpose:** Select *"Providing this key to another website."* - **Name:** Enter a name for the key (e.g., `Lukittu`). - **URL:** Set the URL to: `https://app.lukittu.com` Click **Create Restricted Key**. Copy the generated key. Log in to your Lukittu dashboard. Go to the **Stripe Integration** section. Paste the copied API key into the appropriate field. ## Finishing the Integration Log in to your Lukittu dashboard and go to **Integrations** → **Stripe Integration**. Provide the **restricted API key** you created earlier. Enter the **webhook signing secret** (starting with `whsec_`) from the Stripe webhook configuration. If everything was set up correctly, your Stripe integration should now be fully functional. You can start generating payment links for your Stripe products and selling your software! ## Testing Your Integration * **Switch to Test Mode in Stripe** * Enable **Test Mode** on your Stripe dashboard. * Repeat the steps to set up API keys, webhooks, and products in this isolated environment. * **Test Transactions** * Use Stripe's test credit cards to simulate payments and validate your integration. * **Transition to Production** * Once testing is complete and successful, replicate the setup in **Live Mode** to start selling. # Introduction Source: https://docs.lukittu.com/introduction Lukittu is a modern software licensing service that provides robust APIs to add an additional licensing layer to your software, enhancing security and trackability. This documentation contains all the information you need to get started. Hero Light Hero Dark ## What is Lukittu? Lukittu is an advanced software licensing and distribution system designed to protect proprietary software from unauthorized sharing and misuse. While cloud-based solutions are on the rise, a significant amount of software still operates on clients' machines, bringing unique security challenges. ### Key Benefits * **Enhanced Security**: Prevent unauthorized software distribution through a robust licensing layer * **Usage Analytics**: Track who is using your software, when, and from where * **Easy Integration**: Simple API-driven implementation for your existing software * **Flexible Licensing**: Protect your intellectual property while maintaining user accessibility For paid proprietary software, one of the main concerns is preventing users from illegally distributing the software or repurposing its code for their own solutions. This ongoing battle is often addressed through techniques like code obfuscation—making the client-facing code difficult to reverse engineer. However, obfuscation alone doesn't prevent users from sharing the software. This is where Lukittu steps in. By introducing a **licensing layer** on top of the software, Lukittu ensures that only users with valid license keys can access and use the software. This added protection enhances security and offers several additional benefits, such as providing insights into actual software usage—including who is using the software, when they are using it, and from where. While no solution is 100% foolproof, combining **strong obfuscation** with an **effective software licensing system** provides a robust defense against unauthorized software distribution and misuse. ## Getting Started Getting started with Lukittu is straightforward. Here's what you need to know: ### Prerequisites * A software application that requires licensing protection. Common use cases for Lukittu include game scripts and add-ons running entirely on the client’s server, such as Minecraft, FiveM, Roblox, and more. * Basic understanding of API integration, including REST APIs and WebSockets. * An account on the Lukittu platform. A free tier is available to help you get started. For the actual implementation, refer to the corresponding pages in this documentation. ## Building Your Own Licensing System vs Using Lukittu When considering how to protect your proprietary software, you have two main options: **building your own licensing system** or using a ready-made solution like **Lukittu**. Below, we highlight the pros and cons of each approach to help you make an informed decision. ### Building Your Own Licensing System Custom licensing systems offer maximum control but require significant resources to develop and maintain. #### Advantages * **Customization:** Full control over the licensing process, tailoring it to your software's needs. * **Ownership:** You own and control the system, reducing reliance on third parties. #### Challenges * **Time and Complexity:** Developing a robust system is time-consuming and requires specialized knowledge. * **Ongoing Maintenance:** Security updates and system improvements require continuous effort and resources. * **Cost:** The development and maintenance of a custom solution can be expensive. ### Using Lukittu #### Advantages * **Quick Setup:** Lukittu provides a pre-built, scalable licensing system that integrates easily into your software. * **Security:** Regular updates and built-in protection against piracy and unauthorized sharing. * **Insights:** Gain valuable usage analytics and track activations. * **Cost-Effective:** Lukittu's subscription-based model eliminates the need for upfront costs and the ongoing maintenance of a custom system. We also offer a generous free tier, so you can get started without spending a penny. #### Challenges * **Less Customization:** While highly configurable, Lukittu may not provide the same level of customization as a fully custom-built system. However, if you have specific needs, feel free to contact us—we may be able to implement your requirements. * **Third-Party Dependency:** Using Lukittu means relying on an external service, though it's backed by strong support and security. ### Recommendations Consider your team size and resources carefully when making this decision. What works for a large enterprise may not be suitable for an indie developer. Building your own licensing system should be carefully considered. It might not be worth the significant time, cost, and complexity involved unless you have very specific needs or the resources to support long-term development and maintenance. A custom-built licensing system can be more beneficial, as it offers greater control and scalability, aligning with the complex needs of large organizations. Custom systems are often better suited to handle unique licensing models and tight integration with existing enterprise systems. ## Next Steps Ready to get started with Lukittu? Here's what you can explore next: Get detailed information about our API endpoints and how to use them. Learn how to leverage our third-party integrations effectively. Join our Discord community to get help, share ideas, and connect with other users. # Licenses Source: https://docs.lukittu.com/platform/licenses Licenses are the cornerstone of the Lukittu system, providing access control to your software. Without a valid license, users cannot access your software. License keys enable you to track software usage and prevent unauthorized access. ## License Properties When creating a license in Lukittu, you can configure the following properties: ### License Key Format License keys follow the format `XXXXX-XXXXX-XXXXX-XXXXX-XXXXX`, where X can be any character from A-Z or 0-9. Keys are unique within each team. You can either: * Generate the key automatically through Lukittu * Manually specify a custom key ### Expiration Types #### 1. Never Suitable for lifetime access products. The license will never expire once issued. #### 2. Date Set a specific expiration date for the license. The expiration date is timezone-aware and will be set according to your dashboard's timezone. Example: Setting an expiration date of 12/12/2022 will make the license invalid after that date. #### 3. Duration Specify a time period after which the license expires. You can choose when the expiration countdown begins: * **Creation**: Timer starts when the license is created * **Activation**: Timer starts upon first license activation, generating an expiration date based on the activation date ### Access Limitations #### IP Limitations Restrict the number of unique IP addresses that can use the license. Configure the IP limit period in team settings: * **Day**: Maximum unique IPs per day * **Week**: Maximum unique IPs per week * **Month**: Maximum unique IPs per month #### Concurrent Users Control how many users can simultaneously use the license. This feature: * Tracks usage through heartbeat signals * Uses the "HWID timeout" setting from team settings to determine when a device becomes inactive * Marks devices as inactive if no heartbeat is received within the timeout period **Important**: Dockerized environments may have issues with concurrent user limits due to difficulties in generating unique hardware identifiers. ### Assignment Options #### Product Assignment Restrict license usage to specific products in your portfolio. This is useful when: * Managing multiple products * Creating product-specific licenses * Implementing tiered access #### Customer Assignment Control which customers can use the license: * Assign multiple customers to a single license * Enable shared license functionality * Requires customer ID in authentication requests ### License Status Licenses can have one of five statuses: ACTIVE, INACTIVE, EXPIRING, EXPIRED, or SUSPENDED. The status is automatically determined based on several factors: #### Last Active Date * Tracks when the license was last used * Initially set to license creation date * Updates with each license authentication request * Used to determine inactivity status #### Status Types ##### 1. ACTIVE * Default status for valid, recently used licenses * License is within expiration period * Has been used within last 30 days ##### 2. INACTIVE * No license activity for over 30 days * License is still valid but unused * Applies to all license types ##### 3. EXPIRING * License will expire within 30 days * Only applies to DATE and DURATION type licenses * License is still valid and usable ##### 4. EXPIRED * Past the expiration date * Only applies to DATE and DURATION type licenses * License is no longer valid ##### 5. SUSPENDED * Manually suspended by administrator * Overrides all other status checks * License is temporarily invalid A license is considered inactive if there have been no authentication requests for over 30 days, regardless of its expiration status. #### Suspension * Temporarily disable licenses using the suspension feature * Suspended licenses are considered invalid * Useful for temporary access restriction ### Metadata Store additional license information using metadata: * Custom fields for extra license details * Used by integrations * Flexible data storage for specific use cases # Products Source: https://docs.lukittu.com/platform/products A product in Lukittu represents a software application that you want to manage access to. Through Lukittu's flexible access control system, each license key can grant access to one or multiple products. ## Product Configuration When implementing Lukittu in your application, you should specify which Lukittu product the software represents. While optional, this is recommended for: * Better tracking capabilities * Improved access management * Enhanced usage analytics Product identification is done using a UUID v4 product ID in your implementation. ## Release Management ### Overview Products can maintain multiple releases to track different software versions. This feature provides: * Version tracking across your user base * Integration with remote classloader functionality * Historical version management ### Release States #### 1. Published The standard state for active releases: * Available to all licenses with product access * Can be tagged as "latest" for fallback versioning * Represents production-ready software #### 2. Draft Preparation state for upcoming releases: * Created but not yet publicly available * Allows preparation of release materials * Can be published when ready for deployment #### 3. Archived Historical state for inactive releases: * No longer available for use * Maintained for record-keeping * Useful for audit and tracking purposes #### 4. Deprecated Warning state for sunset releases: * Remains functional and accessible * Includes deprecation notifications * Encourages users to upgrade * Helps manage version transitions ### Latest Release Tag Published releases can receive the "latest" designation: * Only one release can be "latest" at a time * Serves as the default version for unspecified requests * Simplifies version management ### Release Branching Lukittu supports release branching to manage multiple release streams for a single product. This feature is particularly useful when: * Your product has different artifacts for different platforms * You maintain separate release cycles for various environments * You need to distribute platform-specific versions #### How Branching Works Without branches (default behavior): * A product has a single linear release timeline * Only one release can be designated as "latest" * Versioning follows a standard progression (e.g., 1.0.0 → 1.0.1) With branches: * Each branch maintains its own release timeline * Every branch can have its own "latest" release * Versioning is branch-specific * Verify requests can target a specific branch's latest or a specific version #### Branch Use Case This is especially useful for classloader users who distribute Java JAR files to different platforms. Each platform can have its own branch with platform-specific releases while maintaining consistent versioning schemes. ```mermaid theme={null} graph TD %% Main Product Node Product[Product] %% Default Case Section subgraph "Default Release Structure" Product --> Release1.0.0[Release 1.0.0] Product --> Release1.0.1[Release 1.0.1] Release1.0.1 -->|Latest Release| Product end %% Branching Case Section subgraph "Branching Release Structure" ProductB[Product] ProductB --> Branch1[Branch 1] ProductB --> Branch2[Branch 2] ProductB --> DirectRelease[Branchless Releases] Branch1 --> B1R1[Release 1.0.0] Branch1 --> B1R2[Release 1.0.1] B1R2 -->|Latest Branch 1 Release| Branch1 Branch2 --> B2R1[Release 1.0.0] Branch2 --> B2R2[Release 1.0.1] Branch2 --> B2R3[Release 1.0.2] B2R3 -->|Latest Branch 2 Release| Branch2 DirectRelease --> DR1[Release 2.0.0] DirectRelease --> DR2[Release 2.0.1] DR2 -->|Latest Product Release| ProductB end %% Styling classDef product fill:#f9f,stroke:#333,stroke-width:2px classDef branch fill:#bbf,stroke:#333,stroke-width:1px classDef release fill:#bfb,stroke:#333,stroke-width:1px classDef latest fill:#fbb,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5 class Product,ProductB product class Branch1,Branch2,DirectRelease branch class Release1.0.0,Release1.0.1,B1R1,B1R2,B2R1,B2R2,B2R3,DR1,DR2 release ``` #### When to Use Branching Consider using release branching when: * You need to maintain separate builds for different platforms * Your application has different feature sets across deployment targets When implementing verification logic, remember to specify the branch name when targeting branch-specific releases. ### Release Restrictions Control release accessibility through license-specific restrictions: * Enable controlled beta testing * Manage gradual version rollouts * Test with select users before wide release * Create exclusive access for specific licenses ## Best Practices ### Version Naming We recommend following [semver](https://semver.org/) (Semantic Versioning) conventions. Semantic versioning: * Provides clear version hierarchy * Communicates change significance * Maintains industry-standard versioning * Helps users understand update importance # Settings Source: https://docs.lukittu.com/platform/settings Configuration settings for your Lukittu team. ## Team Settings On your team settings page, you can configure the following settings: ### Access Control Settings #### Strict Customers If true, when you have a license key with at least one customer assigned, you need to provide a valid customer ID on each request. #### Strict Products If true, when you have a license key with at least one product assigned, you need to provide a valid product ID on each request. #### Strict Releases If true, when you have a license key with at least one product assigned which has releases, you need to provide a valid release version on each request. ### License Usage Settings #### IP Timeout The time period during which unique IP addresses are counted for IP-limit on license keys. #### HWID Timeout The time period during which unique HWID are counted for HWID-limit on license keys. ### Premium Features #### Email Settings (PRO) ##### Email Header Image The image that will be used in the header of the emails sent by Lukittu. ##### Email Delivery Message A custom message that will be added to the email delivery message. # Webhooks Source: https://docs.lukittu.com/platform/webhooks Use webhooks to receive real-time notifications about events in your Lukittu account. # Webhooks Webhooks allow you to build or set up integrations that subscribe to certain events on Lukittu. When one of those events is triggered, we'll send an HTTP POST payload to the webhook's configured URL. Webhooks can be used to react to events that happens on Lukittu real-time. ## Events You can create webhooks that subscribe to the various events that occur in your team. You can select which events you want to receive when you create the webhook in webhooks tab on the dashboard. Here are some examples of available events: * `LICENSE_CREATED` * `LICENSE_UPDATED` * `LICENSE_DELETED` * `CUSTOMER_CREATED` * `PRODUCT_CREATED` * And many more... ## Securing your webhooks Once your server is configured to receive payloads, it will listen for any payload sent to the endpoint you configured. For security reasons, you should limit requests to those coming from Lukittu. To do so, you'll need to validate the webhook signature. Lukittu uses a HMAC-SHA256 signature to verify the authenticity of the webhook. A secret token is generated for each webhook. On each request, we include the following headers: * `X-Lukittu-Event`: The name of the event that triggered the webhook. * `X-Lukittu-Timestamp`: A UTC timestamp of when the request was sent. * `X-Lukittu-Signature`: The HMAC-SHA256 signature. ### Verifying signatures The signature is generated by creating a HMAC with the SHA256 hash function. The secret for the webhook is used as the key, and the message is the concatenation of the timestamp (as a string) and the raw request body, separated by a dot (`.`). `HMAC-SHA256(secret, timestamp + '.' + requestBody)` You should always use a constant-time string comparison function to compare the expected signature with the received signature to prevent timing attacks. ```javascript Verifying with Node.js theme={null} const crypto = require('crypto'); const LUKITTU_SECRET = process.env.LUKITTU_WEBHOOK_SECRET; function verifySignature(body, headers) { const timestamp = headers['x-lukittu-timestamp']; const signature = headers['x-lukittu-signature']; if (!timestamp || !signature) { throw new Error('Missing signature headers'); } const signedPayload = `${timestamp}.${body}`; const expectedSignature = crypto .createHmac('sha256', LUKITTU_SECRET) .update(signedPayload) .digest('hex'); const trusted = Buffer.from(expectedSignature, 'utf-8'); const untrusted = Buffer.from(signature, 'utf-8'); if (crypto.timingSafeEqual(trusted, untrusted)) { console.log('Signature is valid!'); return true; } else { console.error('Signature is invalid.'); return false; } } ``` ```python Verifying with Python theme={null} import hashlib import hmac LUKITTU_SECRET = "your_webhook_secret" def verify_signature(body, headers): timestamp = headers.get('X-Lukittu-Timestamp') signature = headers.get('X-Lukittu-Signature') if not timestamp or not signature: raise Exception('Missing signature headers') signed_payload = f"{timestamp}.{body}".encode('utf-8') secret = LUKITTU_SECRET.encode('utf-8') expected_signature = hmac.new(secret, signed_payload, hashlib.sha256).hexdigest() if hmac.compare_digest(expected_signature, signature): print("Signature is valid!") return True else: print("Signature is invalid.") return False ``` ## Delivery and Retries Lukittu will attempt to deliver a webhook event to your configured URL. If the delivery fails, we will retry sending it. ### Timeout A webhook delivery will time out after 5 seconds. Ensure your server can process the request within this timeframe. ### Retry Mechanism If your server responds with a non-2xx status code or times out, we will attempt to redeliver the event using an exponential backoff schedule. * **Maximum Retries**: 5 attempts. * **Retry Schedule**: The delay between retries increases exponentially (e.g., 60s, 120s, 240s...). If a webhook continues to fail, it may be automatically disabled. Specifically, if a webhook has 3 or more consecutive failures within a 48-hour period with no successful deliveries, it will be deactivated to prevent further issues. ## Discord Webhooks Lukittu has special support for sending webhooks directly to Discord. If you use a Discord webhook URL, we will automatically format the payload into a Discord-friendly embed format. No signature verification is needed for Discord webhooks. The image above is just an example of how a Discord webhook might look. # General overview Source: https://docs.lukittu.com/security/general Lukittu client-server communication employs a sophisticated hybrid cryptographic system that combines both asymmetric (RSA 2048) and symmetric encryption to ensure maximum security and integrity. This documentation provides a detailed overview of the communication processe ## Introduction Lukittu client-server communication employs a sophisticated hybrid cryptographic system that combines both asymmetric (RSA 2048) and symmetric encryption to ensure maximum security and integrity. This documentation provides a detailed overview of the communication processes. ## HTTP Communication Security The general HTTP communication between client and server implements asymmetric cryptography with the following characteristics: * Server maintains an RSA 2048 key pair: * Private key (secured on server) * Public key (distributed to clients) * Clients possess only the server's public key * Challenge-response verification ensures request authenticity * All transmitted data is cryptographically signed ### HTTP Communication Flow ```mermaid theme={null} sequenceDiagram participant Client participant Server Note over Server: RSA 2048 key pair:
Private key (secured)
Public key (distributed) Note over Client: Generate cryptographic challenge Client->>Server: Send request Note over Client,Server: Request payload:
1. Cryptographic challenge
2. Request body data
Note over Server: 1. Sign challenge with
private key (RSA 2048) Server->>Client: Send response Note over Client,Server: Response payload:
1. Digital signature
2. Response data
Note over Client: Security checks:
1. Verify RSA 2048 signature
2. Validate challenge match
alt All security checks pass Note over Client: Process validated response else Any check fails Note over Client: Reject response
Log security exception end ``` ## Classloader Security Architecture The Classloader implements an advanced encryption scheme that protects both data in transit and ensures secure class loading: * Uses RSA 2048 for key exchange * Implements AES-256-GCM for chunk encryption * Maintains zero-persistence security model * Employs session-based encryption with rotating keys ### Classloader Communication Flow ```mermaid theme={null} sequenceDiagram participant Client as Client Classloader participant Backend as Lukittu Backend participant Memory as Client Memory Note over Client: 1. Generate random session ID
2. Access RSA 2048 public key Client->>Client: Encrypt session ID using
RSA 2048 OAEP padding Client->>Backend: Send encrypted session ID
+ authentication parameters Note over Backend: 1. RSA 2048 private key
2. Security validation suite Backend->>Backend: 1. RSA decrypt session ID
2. Validate session parameters
3. Verify license credentials Backend->>Backend: Generate AES session key loop For each class chunk Backend->>Backend: 1. AES-256-GCM encryption
2. Generate auth tag Backend->>Client: Stream encrypted chunk + IV Client->>Client: 1. Verify auth tag
2. Decrypt with session key Client->>Memory: Load verified class Note over Memory: Zero-persistence:
Classes only exist in memory end Note over Client,Memory: Runtime security:
No persistence to disk
```