Démarrer

Générer des licences

Durées, modes d’expiration, génération en masse et automatisation depuis votre boutique.

Format : PREFIX-XXXX-XXXX-XXXX-XXXX, 16 caractères Base32 Crockford (80 bits d’aléa, générateur cryptographique). La saisie tolère casse, espaces et confusions O/0, I/1.

Durées et expiration

ModeComportement
from_first_activationLa durée démarre à la première activation (défaut).
from_creationLa durée démarre à la génération.
fixed_dateExpire à expires_at.
neverLicence à vie.

Préréglages : trial (durée d’essai de l’application), 1d, 3d, 7d, 30d, 90d, 1y, lifetime, custom (avec duration_seconds).

Depuis votre boutique

Après un paiement, créez la licence depuis votre serveur avec une clé API signée et une clé d’idempotence (un nouvel essai ne crée pas de doublon) :

TypeScript (serveur)
import { createHash, createHmac, randomBytes } from 'node:crypto';

// Création d'une licence depuis votre boutique après paiement (serveur uniquement).
async function createLicenseForOrder(orderId: string, email: string) {
  const path = '/api/v1/admin/licenses';
  const body = JSON.stringify({ application_id: APP_ID, product_id: PRODUCT_ID, note: `Commande ${orderId}` });
  const ts = Math.floor(Date.now() / 1000).toString();
  const nonce = randomBytes(16).toString('base64url');
  const canonical = ['POST', path, ts, nonce, createHash('sha256').update(body).digest('hex')].join('\n');
  const res = await fetch(`https://keyline.example.com${path}`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.KEYLINE_API_KEY}`,
      'Content-Type': 'application/json',
      'Keyline-Timestamp': ts,
      'Keyline-Nonce': nonce,
      'Keyline-Signature': `v1=${createHmac('sha256', process.env.KEYLINE_SIGNING_SECRET!).update(canonical).digest('hex')}`,
      'Idempotency-Key': `order-${orderId}`, // un nouvel essai ne crée pas de doublon
    },
    body,
  });
  const { license, license_key } = await res.json();
  await sendLicenseEmail(email, license_key); // seule occasion d'obtenir la clé en clair
  return license.id;
}

Génération en masse : POST /api/v1/admin/licenses/bulk avec count (1 à 1000).

Cycle de vie

  • Suspendre : réversible, sessions coupées.
  • Révoquer : définitif, sessions coupées.
  • Renouveler : ajoute une durée à la date la plus tardive entre maintenant et l’expiration, ou fixe une date.
  • Réinitialiser les appareils : libère toutes les activations (le quota d’activations consommées n’est pas restitué).
  • Expiration automatique : détectée à chaque appel et par une tâche périodique ; événement license.expired.