Skip to main content
License keys are the License Key entitlement type. Create a License Key entitlement once with the activation limit, expiry, and activation message you want, then attach it to any product. By default, Dodo Payments generates and emails one key for each unit purchased or each subscription seat.

What Are License Keys?

A license key is a unique token that authorizes access to your product. Use license keys for:
  • Software licensing: desktop apps, plugins, and CLIs.
  • Per-seat controls: limit activations per user or device.
  • Digital goods: gate downloads, updates, or premium features.
Dodo Payments manages license keys through Entitlements. The same payment and subscription events that drive your other entitlements drive each key’s lifecycle: creation, expiry, revocation, and re-grant.

Create a License Key Entitlement

1

Open Entitlements

Go to Entitlements in the dashboard and click + to create an entitlement.
2

Choose License Key

Select License Keys, enter a Name, and configure how each issued key behaves:
  • Fulfillment Mode: Automatic (the default) generates and emails each key. Manual lets you supply each key yourself. See Manual Fulfillment.
  • Activations Limit: the maximum number of active activations per key, for example 1 for a single user or 5 for a team license. Select Unlimited for no limit.
  • License Length: how long a key stays valid after it’s issued, for example 30 days or 1 year, or No expiration. For subscription products, choose No expiration: keys issued for a subscription have no expiry, and their validity follows the subscription status.
  • Activation Message: optional customer-facing instructions, up to 2,500 characters, included in the email that delivers the key. For example: Paste the key in Settings → License or Run: mycli activate <key>.
New License Key entitlement form with name, fulfillment mode, license length, activations limit, and activation message
3

Save the Entitlement

Click Create Entitlement. You can now attach the entitlement to any product.

Attach to Products

Open a product, go to its Entitlements section, and select your License Key entitlement. One product can deliver a license key together with other entitlements on the same purchase, such as Discord access, file downloads, or GitHub repository access.
Product entitlements panel with License Key selected

Selecting the License Key entitlement in the product entitlements panel.


How Keys Are Issued

Key issuance follows the standard grant lifecycle. Each event affects license keys as follows:

Quantity Behavior

The number of keys depends on where the grant comes from. Each key gets its own grant.
  • Subscription products issue one key per seat (subscriptions.quantity).
  • One-time products issue one key per unit of the cart line item (product_cart.quantity).
  • Manual API grants issue exactly one key.

Fulfillment Mode

Every License Key entitlement has a fulfillment_mode that controls who supplies the key:
  • auto (default, Automatic in the dashboard): Dodo Payments generates and emails the key on payment or subscription. This is the behavior in the table above, and it applies when fulfillment_mode is omitted.
  • manual (Manual in the dashboard): each unit purchased creates a Pending grant with no key, and you supply each key value. See Manual Fulfillment.

Manual Fulfillment

With manual fulfillment, you supply each license key instead of Dodo Payments generating it. The purchase creates a Pending grant with no key, notifies you with a webhook, and waits for you to submit the key value. Use it when keys come from your own system, a third-party vendor, or a finite pool of pre-printed codes.
For a step-by-step build, from product creation to key delivery, see the Manual License Key Fulfillment Integration Guide.

When to Use It

Automatic fulfillment suits most software licensing. Choose manual fulfillment when Dodo Payments can’t generate the key itself:
  • Bring your own keys: your application, a desktop product, or your own license server generates the key.
  • Third-party vendors: you resell keys that an upstream provider issues, such as a game key, an API credential, or a partner platform license.
  • Finite inventory: you hand out codes from a pre-allocated pool and assign them one at a time.
  • Human review: you want to check a purchase before you release access.

Enable Manual Fulfillment

To enable manual fulfillment through the API, set fulfillment_mode: "manual" in the License Key entitlement’s integration_config. In the dashboard, set Fulfillment Mode to Manual.
fulfillment_mode is backward compatible. Entitlements created before this setting existed have no fulfillment_mode and behave as auto. Switching to manual affects only grants created after the change. Keys already delivered don’t change.

Find Grants Awaiting Fulfillment

When a customer buys a product with a manual-mode entitlement, Dodo Payments creates the grant in Pending status with no key and sends an entitlement_grant.created webhook with integration_type: "license_key" and status: "Pending". React to that webhook, or poll the List Customer Grants endpoint with the integration_type and status filters:

Deliver the Key

To deliver a key, send it to the Fulfill License Key Grant endpoint. The grant moves to Delivered, and Dodo Payments emails the key to the customer. It’s the same email the customer receives under automatic fulfillment.
cURL
activations_limit and expires_at are optional. When you omit them, Dodo Payments uses the entitlement’s configuration. Each grant can be fulfilled once: retrying an already-fulfilled grant returns 409 instead of issuing a second key.
You don’t need to email the key yourself. Dodo Payments delivers it when the grant is fulfilled. Importing keys with POST /license_keys works differently: it does not notify the customer.

Activation, Validation, Deactivation

Your software manages a key at runtime through three endpoints. Activation records a device or installation against the key, validation checks that the key is usable, and deactivation frees an activation.
Public Endpoints: The activate, deactivate, and validate license endpoints are public and don’t require an API key. Call them directly from desktop software, CLIs, or browser-based clients without exposing your API credentials. The SDK constructors still require a bearer token value, so the SDK examples pass a placeholder.

Activate a License

Activation creates an activation instance for the key and returns it with an lki_ ID. Store that ID, because you need it to deactivate the instance. The request returns 403 if the key isn’t active, 404 if the key doesn’t exist, and 422 if the key has reached its activation limit.

Validate a License

Validation returns valid: true when the key’s status is active and the key hasn’t expired. To also check that a specific activation instance still exists, pass its license_key_instance_id.

Deactivate an Activation Instance

Deactivation removes an activation instance and frees one activation on the key. Pass the key and the instance ID that activation returned. The request returns 403 if the instance doesn’t belong to the key, and 404 if the key doesn’t exist.

Manage Keys

To see issued keys, open the License Key entitlement under Entitlements. The grants list shows one row per customer key, with the customer, the date accessed, the status, and a Revoke action. To see a key’s expiry, activation count, and activation limit, open it under Sales → License Keys. To list grants programmatically, call List Grants. On each license-key grant, the license_key object carries the key, status, expiry, activations used, and activations limit. The object is null on a manual-mode grant that’s still Pending.

Import Existing License Keys via API

To migrate license keys from another system, import them with the Create License Key API. Your customers keep activating, validating, and deactivating the same key strings, so you don’t need to reissue keys.
License keys created or updated through the API do not trigger email notifications to customers. To tell customers about an imported key, notify them from your own application.
The request requires key, customer_id, and product_id. Omit activations_limit for unlimited activations, and omit expires_at for a key that never expires. Importing a key string that already exists returns 409.

How Keys Differ by Source

The source field records how each license key was created: Use source to tell migrated and manually fulfilled keys apart from keys that Dodo Payments generated, for example when you reconcile or audit keys. The field is on license key records, such as the POST /license_keys response. The license_key object on grants from List Grants doesn’t include it. The legacy GET /license_keys endpoint, which returns source and accepts a source filter, is deprecated.
Migrating from Polar.sh or Lemon Squeezy? The dodo-migrate CLI imports products, customers, discounts, and license keys in bulk with a single command, and maps external IDs to Dodo Payments IDs.

License Keys in Return URL

When a customer buys a product with a License Key entitlement, Dodo Payments appends the generated key to your return_url as the license_key query parameter. Your success page can show the key without an extra API call:
If the purchase generates more than one key (quantity above 1), the parameter holds a comma-separated list. The comma is URL-encoded as %2C, so read the parameter with a URL parser, which decodes it, before you split it:
For subscriptions, the URL carries subscription_id and the subscription status instead of payment_id:
Read the license_key parameter on your return page to show the key right after purchase.

API Management

Activation, deactivation, and validation are public and require no API key.

Activate License

Create an activation instance for a license key.

Deactivate License

Remove an activation instance to free up capacity.

Validate License

Check that a key is active and unexpired before you grant access.
Create, list, retrieve, and update individual license key records. Use these endpoints to import existing keys or read usage details.
GET /license_keys, GET /license_keys/{id}, and PATCH /license_keys/{id} are deprecated. For reads, use the entitlement grant endpoints (List Grants, List Customer Grants). POST /license_keys remains supported for importing existing keys.

Create License Key

Create a license key or import an existing one.

List License Keys

Browse all keys with status and usage details.

Get License Key

Retrieve a specific key and its metadata.

Update License Key

Change the expiry or activation limit, or enable or disable a key.
Manage the License Key entitlement itself: its activation limit, license length, and activation message.

Create Entitlement

Create a License Key entitlement.

Update Entitlement

Update the entitlement’s configuration.

List Grants

List the keys issued for an entitlement.

Revoke Grant

Revoke a customer’s key manually.

Webhooks

License key delivery and revocation send the four entitlement_grant.* webhook events. For license-key grants, the payload includes a license_key object with the key, status, expiry, activations used, and activations limit. The legacy license_key.created event still fires when a license key record is created. See the License Key webhook payload page.
For new integrations, handle entitlement grant events instead of license_key.created. An auto-fulfilled key arrives as entitlement_grant.created with status: "Delivered", and no separate entitlement_grant.delivered event follows. A manually fulfilled key fires entitlement_grant.delivered when you supply it. The same events cover every entitlement on the product, not only the license key.

Legacy License Keys

Products created with the older license_key_enabled flag have been automatically migrated to a License Key entitlement. The migration is transparent: existing customers’ keys keep working, the public /licenses/activate, /licenses/validate, and /licenses/deactivate endpoints keep working, and the /license_keys/* API endpoints read and write the same key store.The standalone Sales → License Keys dashboard section remains available as a flat list of every key issued, for audit and search. To change activation limits, license length, or the activation message, edit the migrated License Key entitlement under Entitlements.

Best Practices

  • Choose clear activation limits: pick defaults such as 1 for single-user apps or 3–5 for team licenses, and document them for your customers.
  • Write precise activation messages: customers copy them from the license key email, so exact paths and commands prevent support tickets.
  • Validate keys against the API: for network-connected products, call /licenses/validate instead of relying on a locally cached activation.
  • Use webhooks for revocation: handle entitlement_grant.revoked to disable in-app features when a customer cancels or receives a refund.
  • Test subscriptions and one-time purchases: license key behavior differs between the two, for example subscription keys don’t expire, so test both before you go live.
Last modified on September 25, 2026