> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# License Keys

> Generate and deliver unique license keys with activation limits and expiry. License keys are the License Key entitlement type. They're issued automatically on payment, tied to subscription lifecycle, and revoked on cancellation or refund.

<Frame>
  <iframe className="w-full aspect-video rounded-md" src="https://www.youtube.com/embed/BNuLTXok8dQ" title="License Keys | Dodo Payments" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen />
</Frame>

<Info>
  License keys are the License Key entitlement type. Create a License Key entitlement once with the activation limit, expiry, and instructions you want, attach it to any product, and Dodo Payments generates and delivers a key per purchase or subscription seat, automatically.
</Info>

## What are License Keys?

License keys are unique tokens that authorize access to your product. They're ideal 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

Inside Dodo Payments, license keys are managed through the [Entitlements](/features/entitlements/introduction) system, meaning the lifecycle of every key (creation, expiry, revocation, regrant) is driven by the same payment and subscription events as your other deliverables.

## Create a License Key Entitlement

<Steps>
  <Step title="Open Entitlements">
    Go to **Entitlements** in your Dodo Payments dashboard and click **+** to create a new entitlement.
  </Step>

  <Step title="Choose License Key">
    Select **License Key** as the integration. Configure how each issued key behaves:

    * **Activations Limit**: Maximum concurrent activations per key (e.g., `1` for single-user, `5` for team licenses, leave blank for unlimited).
    * **Duration**: How long the key stays valid after issuance (e.g., 30 days, 1 year). For subscription-issued keys, leave blank; keys remain valid as long as the subscription is active.
    * **Activation Instructions**: Customer-facing instructions emailed with the key. Examples: `Paste the key in Settings → License` or `Run: mycli activate <key>`.

    <Frame>
      <img src="https://mintcdn.com/dodopayments/sZYZEc6Biy3IrQNZ/images/entitlements/license-keys/create.png?fit=max&auto=format&n=sZYZEc6Biy3IrQNZ&q=85&s=65f24596e834387d0c35278ef92d14ea" alt="Nouveau formulaire d'agrément de clé de licence avec nom, mode de réalisation, durée de la licence, limite d'activations et message d'activation" style={{ maxHeight: '500px', width: 'auto' }} width="2840" height="1614" data-path="images/entitlements/license-keys/create.png" />
    </Frame>
  </Step>

  <Step title="Save the entitlement">
    Save. The entitlement is now available to attach to any product.
  </Step>
</Steps>

## Attach to Products

Open a product, expand **Advanced Settings → Entitlements & Credits**, and select your License Key entitlement. A single product can deliver a license key alongside other entitlements (Discord access, file downloads, GitHub repo access, etc.) on the same purchase.

<Frame caption="Selecting the License Key entitlement in the product entitlements panel.">
  <img src="https://mintcdn.com/dodopayments/do-W-dMDGVB_xzr_/images/entitlements/attach-to-product.png?fit=max&auto=format&n=do-W-dMDGVB_xzr_&q=85&s=965ad78262791fa8dbb712b4fdf89538" alt="Product entitlements panel with License Key selected" style={{ maxHeight: '500px', width: 'auto' }} width="2000" height="1197" data-path="images/entitlements/attach-to-product.png" />
</Frame>

***

## How Keys Are Issued

Key issuance follows the standard [grant lifecycle](/features/entitlements/introduction#how-grants-work):

| Event                                | Behavior                                                                                                                   |
| ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| `payment.succeeded` (one-time)       | Generate one key per `quantity` purchased. Key expiry honors the entitlement's duration.                                   |
| `subscription.active`                | Generate one key per subscription `quantity` (seat). Key has no expiry; validity is tied to subscription status.           |
| `subscription.renewed`               | No-op. Existing keys persist.                                                                                              |
| `subscription.on_hold`               | Disable the keys. They reactivate when the subscription comes off hold.                                                    |
| `subscription.cancelled` / `expired` | Disable the keys permanently.                                                                                              |
| `subscription.plan_changed`          | Disable the old keys; issue new ones for the new plan.                                                                     |
| `refund.succeeded` (one-time)        | Disable the keys.                                                                                                          |
| Manual revoke via API/dashboard      | Disable the keys with `revocation_reason: manual`. These are not auto-regranted on subscription renewal.                   |
| License key disabled directly        | Revoke the grant with `revocation_reason: license_key_disabled`. Re-enabling the key re-activates the grant automatically. |

### Quantity behavior

* **Subscription products** issue one key per seat (`subscriptions.quantity`).
* **One-time products** issue one key per cart line item (`product_cart.quantity`).
* **Manual API grants** issue exactly one key.

### Mode de réalisation

Chaque agrément de clé de licence a un `fulfillment_mode` qui contrôle qui fournit la clé :

* **`auto`** (par défaut) : Dodo Payments génère et envoie automatiquement la clé par e-mail lors du paiement ou de l'abonnement. C'est le comportement décrit ci-dessus et s'applique lorsque `fulfillment_mode` est omis.
* **`manual`** : L'achat crée une subvention `pending` sans clé, et vous fournissez vous-même chaque valeur de clé. Voir [Réalisation manuelle](#manual-fulfillment) ci-dessous.

***

## Réalisation manuelle

Par défaut, Dodo Payments génère et envoie par e-mail une clé de licence dès qu'un client paie. Avec la **réalisation manuelle**, vous fournissez vous-même la clé : l'achat crée une subvention `pending` sans clé, vous en informe et attend que vous soumettiez la valeur de la clé. Utilisez-le lorsque les clés proviennent de votre propre système, d'un fournisseur tiers ou d'un pool fini de codes pré-imprimés.

<Info>
  Vous recherchez une construction étape par étape ? Consultez le [Guide d'intégration de la réalisation manuelle des clés de licence](/developer-resources/manual-license-key-fulfillment) pour une présentation complète depuis la création du produit jusqu'à la livraison de la clé.
</Info>

### Quand l'utiliser

La réalisation automatique est le bon choix par défaut pour la plupart des licences logicielles. Choisissez la réalisation manuelle lorsque Dodo Payments ne peut pas générer la clé elle-même :

* **Utilisation de vos propres clés** : La clé est générée par votre application, un produit de bureau ou votre propre serveur de licences.
* **Fournisseurs tiers** : Vous revendez des clés émises par un fournisseur en amont (une clé de jeu, une crédentielle API, une plateforme partenaire).
* **Inventaire fini** : Vous distribuez des codes à partir d'un pool pré-allocé et souhaitez les attribuer un par un.
* **Examen humain** : Vous souhaitez vérifier un achat avant de libérer l'accès.

### Activer la réalisation manuelle

Définissez `fulfillment_mode: "manual"` dans la configuration d'intégration de l'agrément de clé de licence :

<CodeGroup>
  ```typescript Node.js theme={null} theme={null}
  const entitlement = await client.entitlements.create({
    name: 'Pro License (Manual)',
    integration_type: 'license_key',
    integration_config: {
      fulfillment_mode: 'manual',
      activations_limit: 5,
      duration_count: 1,
      duration_interval: 'Year',
    },
  });
  ```

  ```bash cURL theme={null} theme={null}
  curl -X POST https://test.dodopayments.com/entitlements \
    -H "Authorization: Bearer $DODO_PAYMENTS_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Pro License (Manual)",
      "integration_type": "license_key",
      "integration_config": {
        "fulfillment_mode": "manual",
        "activations_limit": 5,
        "duration_count": 1,
        "duration_interval": "Year"
      }
    }'
  ```
</CodeGroup>

<Note>
  `fulfillment_mode` est rétrocompatible. Les agréments créés avant que ce paramètre n'existe n'ont pas `fulfillment_mode` et continuent de se comporter comme `auto`. Passer à `manual` n'affecte que les subventions créées **après** le changement ; les clés déjà livrées restent inchangées.
</Note>

### Trouver les subventions en attente de réalisation

Lorsqu'un client achète un produit en mode manuel, le droit est créé avec le statut `pending` sans clé et un webhook [`entitlement_grant.created`](/developer-resources/webhooks/intents/entitlement-grant) se déclenche avec `integration_type: "license_key"` et `status: "pending"`. Vous pouvez réagir à ce webhook ou interroger le point de terminaison [List Customer Grants](/api-reference/entitlements/list-customer-grants) avec les filtres `integration_type` et `status` :

```typescript theme={null} theme={null}
const pending = await client.customers.listEntitlementGrants('customer_id', {
  integration_type: 'license_key',
  status: 'Pending',
});
```

### Livrer la clé

Soumettez la clé avec le point de terminaison [Fulfill License Key Grant](/api-reference/entitlements/fulfill-license-key). La subvention passe à `delivered` et le client reçoit la clé automatiquement - le même e-mail qu’il recevrait sous réalisation automatique.

```bash cURL theme={null} theme={null}
curl -X POST https://test.dodopayments.com/grants/grant_8VbC6JDZ/license-key \
  -H "Authorization: Bearer $DODO_PAYMENTS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "PRO-AAAA-BBBB-CCCC-DDDD",
    "activations_limit": 5,
    "expires_at": "2027-05-01T00:00:00Z"
  }'
```

`activations_limit` et `expires_at` sont facultatifs et se réfèrent à la configuration de l'agrément lorsqu'ils sont omis. Chaque subvention peut être réalisée une fois ; réessayer une subvention déjà réalisée retourne `409` au lieu d'émettre une seconde clé.

<Check>
  Il n'est pas nécessaire d'envoyer la clé par e-mail vous-même - la livraison se fait automatiquement lorsque la subvention est réalisée. Cela diffère de [l'importation de clés](#import-existing-license-keys-via-api) via `POST /license_keys`, qui n’informe intentionnellement pas le client.
</Check>

***

## Activation, Validation, Désactivation

Les points de terminaison d'activation/validation/désactivation API sont **publics** et ne nécessitent pas de clé API. Utilisez-les directement depuis les logiciels de bureau, les CLI ou les clients basés sur le navigateur pour vérifier les clés à l'exécution.

<Info>
  **Points de terminaison publics** : Les points de terminaison pour activer, désactiver et valider les licences sont publics et ne nécessitent pas de clé API. Appelez-les directement depuis vos applications clientes sans exposer vos identifiants API.
</Info>

### Activer une licence

<CodeGroup>
  ```typescript TypeScript theme={null} theme={null}
  import DodoPayments from 'dodopayments';

  // No API key needed for public license endpoints
  const client = new DodoPayments();

  const response = await client.licenses.activate({
    license_key: 'PRO-AAAA-BBBB-CCCC-DDDD',
    name: 'Device Name',
  });

  console.log(response.id);
  ```

  ```python Python theme={null} theme={null}
  client.licenses.activate(
      license_key="PRO-AAAA-BBBB-CCCC-DDDD",
      name="Device Name",
  )
  ```

  ```bash cURL theme={null} theme={null}
  curl -X POST https://test.dodopayments.com/licenses/activate \
    -H "Content-Type: application/json" \
    -d '{
      "license_key": "PRO-AAAA-BBBB-CCCC-DDDD",
      "name": "Device Name"
    }'
  ```
</CodeGroup>

### Valider une licence

<CodeGroup>
  ```typescript TypeScript theme={null} theme={null}
  const response = await client.licenses.validate({
    license_key: 'PRO-AAAA-BBBB-CCCC-DDDD',
  });

  console.log(response.valid);
  ```

  ```bash cURL theme={null} theme={null}
  curl -X POST https://test.dodopayments.com/licenses/validate \
    -H "Content-Type: application/json" \
    -d '{ "license_key": "PRO-AAAA-BBBB-CCCC-DDDD" }'
  ```
</CodeGroup>

### Désactiver une instance d'activation

```typescript theme={null} theme={null}
await client.licenses.deactivate({
  license_key: 'PRO-AAAA-BBBB-CCCC-DDDD',
  license_key_instance_id: 'instance_abc123',
});
```

***

## Gérer les clés

Ouvrez l'agrément de clé de licence depuis votre tableau de bord pour voir chaque subvention (une ligne par clé client) avec la date de livraison, le nombre d'activations et une action de révocation. Chaque détail de subvention affiche la clé de licence sous-jacente, l'expiration, les activations utilisées et la limite d'activations.

Vous pouvez également lister les subventions de manière programmatique :

```typescript theme={null} theme={null}
const grants = await client.entitlements.grants.list('ent_license_key_id', {
  status: 'Delivered',
});

for (const grant of grants.items) {
  console.log(grant.license_key.key, grant.license_key.activations_used);
}
```

## Importer des clés de licence existantes via l'API

Avez-vous déjà des clés de licence dans un autre système ? Utilisez l'API [Create License Key](/api-reference/licenses/create-license-key) pour les importer dans Dodo Payments. Cela vous permet de migrer les clés existantes sans perturber vos clients - ils continuent d'activer, de valider et de désactiver avec les mêmes chaînes de clés sans réémission.

<Warning>
  Les clés de licence créées ou mises à jour via l'API ne déclenchent pas de notifications par e-mail aux clients. Si vous devez informer les clients d'une clé importée, gérez cela séparément dans votre application.
</Warning>

```typescript theme={null} theme={null}
const licenseKey = await client.licenseKeys.create({
  customer_id: 'cus_abc123',
  product_id: 'prod_456',
  key: 'YOUR-EXISTING-LICENSE-KEY',
  activations_limit: 5,
  expires_at: '2026-12-31T23:59:59Z',
});
```

### Comment les clés diffèrent selon la source

| Champ                             | Clé auto-générée                           | Clé réalisée manuellement                                                   | Clé importée                              |
| --------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------- | ----------------------------------------- |
| `source`                          | `"auto"`                                   | `"manual"`                                                                  | `"import"`                                |
| Origine                           | Générée par Dodo Payments lors du paiement | [Fournie par vos soins](#manual-fulfillment) pour une subvention en attente | Créée/migrée via `POST /license_keys`     |
| `payment_id`                      | Défini sur le paiement d'origine           | Résolu depuis la subvention ou son abonnement                               | `null` (aucune transaction Dodo Payments) |
| `subscription_id`                 | Défini si émise via un abonnement          | Défini si la subvention provient d'un abonnement                            | `null` sauf lien explicité                |
| Notification par e-mail au client | Envoyée lors de l'émission                 | Envoyée lors de la réalisation                                              | Non envoyée - gérée séparément            |

Utilisez le champ `source` sur les réponses `GET /license_keys` pour distinguer l'inventaire migré et les clés réalisées manuellement des clés émises de manière organique lors de la réconciliation ou de l'audit.

<Tip>
  Vous migrez depuis **Polar.sh** ou **Lemon Squeezy** ? Le [CLI `dodo-migrate`](/migrate-to-dodo) automatise les importations en masse de produits, clients, réductions, et clés de licence en une seule commande et associe automatiquement les IDs externes aux IDs Dodo.
</Tip>

***

## Clés de licence dans l'URL de retour

Lorsqu'un client finalise un achat pour un produit avec un agrément de clé de licence, la clé générée est automatiquement ajoutée à votre `return_url` en tant que paramètre de requête. Cela vous permet d'afficher la clé immédiatement sur votre page de réussite sans effectuer un appel d'API supplémentaire.

```text theme={null} theme={null}
https://yoursite.com/return?payment_id=pay_xxx&status=succeeded&license_key=LK-001&email=customer%40example.com
```

Si l'achat génère plusieurs clés (quantité > 1), elles sont séparées par des virgules :

```text theme={null} theme={null}
https://yoursite.com/return?payment_id=pay_xxx&status=succeeded&license_key=LK-001,LK-002&email=customer%40example.com
```

Pour les abonnements, `subscription_id` est utilisé au lieu de `payment_id` :

```text theme={null} theme={null}
https://yoursite.com/return?subscription_id=sub_xxx&status=active&license_key=LK-001&email=customer%40example.com
```

<Tip>
  Analysez le paramètre `license_key` sur votre page de retour pour afficher immédiatement la clé, améliorant ainsi l'expérience post-achat.
</Tip>

***

## Gestion API

<AccordionGroup>
  <Accordion title="Lifecycle Operations (Public Endpoints)">
    Activation, désactivation et validation sont publiques ; aucune clé API requise.

    <CardGroup cols={3}>
      <Card title="Activate License" icon="code" href="/api-reference/licenses/activate-license">
        Créez ou enregistrez une instance d'activation pour une clé de licence.
      </Card>

      <Card title="Deactivate License" icon="code" href="/api-reference/licenses/deactivate-license">
        Révoquez une activation précédente pour libérer de la capacité.
      </Card>

      <Card title="Validate License" icon="code" href="/api-reference/licenses/validate-license">
        Vérifiez l'authenticité, le statut et les contraintes avant d'accorder l'accès.
      </Card>
    </CardGroup>
  </Accordion>

  <Accordion title="License Key Management">
    Créez, listez, récupérez et mettez à jour les enregistrements individuels de clés de licence. Utilisez-les pour importer des clés existantes ou récupérer des détails d'utilisation.

    <CardGroup cols={2}>
      <Card title="Create License Key" icon="code" href="/api-reference/licenses/create-license-key">
        Créez une nouvelle clé de licence ou importez-en une existante.
      </Card>

      <Card title="List License Keys" icon="code" href="/api-reference/licenses/list-license-keys">
        Parcourez toutes les clés avec leur statut et les détails d'utilisation.
      </Card>

      <Card title="Get License Key" icon="code" href="/api-reference/licenses/get-license-key">
        Récupérez une clé spécifique et ses métadonnées.
      </Card>

      <Card title="Update License Key" icon="code" href="/api-reference/licenses/update-license-key">
        Modifiez l'expiration, les limites d'activation ou activez/désactivez une clé.
      </Card>
    </CardGroup>
  </Accordion>

  <Accordion title="Entitlement Management">
    Gérez l'agrément de clé de licence lui-même : sa limite d'activation, sa durée et ses instructions.

    <CardGroup cols={2}>
      <Card title="Create Entitlement" icon="plus" href="/api-reference/entitlements/create-entitlement">
        Créez un agrément de clé de licence.
      </Card>

      <Card title="Update Entitlement" icon="pen" href="/api-reference/entitlements/update-entitlement">
        Mettez à jour la configuration de l'agrément.
      </Card>

      <Card title="List Grants" icon="users" href="/api-reference/entitlements/list-grants">
        Listez les clés émises pour un agrément.
      </Card>

      <Card title="Revoke Grant" icon="ban" href="/api-reference/entitlements/revoke-grant">
        Révoquez manuellement la clé d'un client.
      </Card>
    </CardGroup>
  </Accordion>
</AccordionGroup>

***

## Webhooks

La livraison et la révocation des clés de licence déclenchent les quatre [événements webhook `entitlement_grant.*`](/developer-resources/webhooks/intents/entitlement-grant). La charge utile de la subvention inclut un objet `license_key` peuplé avec la clé, l'expiration, les activations utilisées et la limite.

Les événements hérités `license_key.*` (`license_key.created`) continuent de s'exécuter pour le cycle de vie de l'enregistrement de la clé de licence sous-jacent ; consultez la [page de charges utiles du webhook de clé de licence](/developer-resources/webhooks/intents/license-key).

<Tip>
  Pour les nouvelles intégrations, écoutez `entitlement_grant.delivered` plutôt que `license_key.created`. L'événement d'agrément vous indique que la livraison est complète sur toutes les intégrations du produit, pas seulement la clé de licence.
</Tip>

***

## Clés de Licence Héritées

<Note>
  Les produits créés avec l'ancien drapeau `license_key_enabled` ont été **automatiquement migrés** vers un agrément de clé de licence. La migration est transparente : les clés des clients existants continuent de fonctionner sans changement, les points de terminaison publics `/licenses/activate`, `/licenses/validate`, `/licenses/deactivate` continuent de fonctionner, et les points de terminaison API `/license_keys/*` continuent de lire et d'écrire dans le même magasin de clés.

  La section de tableau de bord **Clés de Licence** autonome reste disponible en tant que liste à plat de chaque clé émise, utile pour l'audit et la recherche. La nouvelle configuration (changement des limites d'activation, des durées, ou des instructions) doit être effectuée en modifiant l'agrément de clé de licence migré sous **Entitlements**.
</Note>

***

## Meilleures Pratiques

* **Gardez les limites d'activation claires** : Choisissez des valeurs par défaut sensées (1 pour les applications à utilisateur unique, 3-5 pour les licences d'équipe) et documentez-les.
* **Fournissez des instructions d'activation précises** : Les clients copient ces informations depuis leur e-mail, donc des chemins et des commandes exacts réduisent les demandes d'assistance.
* **Validez les clés côté serveur** : Pour les produits connectés au réseau, validez via `/licenses/validate` plutôt qu'en mettant en cache l'activation localement.
* **Utilisez les webhooks pour la révocation** : Écoutez `entitlement_grant.revoked` pour désactiver les fonctionnalités de l'application immédiatement lorsqu'un client annule ou demande un remboursement.
* **Testez avec des abonnements et des achats uniques** : Le comportement des clés de licence diffère subtilement entre les deux, alors testez les deux avant de lancer.
