Docs

Tout ce dont vous avez besoin pour intégrer SublimeKeys à votre app. Aucun compte requis pour les lire.

$SUBLIMEKEYS_API_KEY

Chaque requête ci-dessous utilise ceci comme espace réservé pour votre vraie clé. Se connecter (gratuit, sans carte) pour obtenir la vôtre et voir ces exemples remplis avec votre propre produit.

DÉMARRAGE RAPIDE — 3 APPELS

1. Enregistrez votre produit (fait une seule fois, dans Produits)

curl -X POST https://api.sublimearts.io/v1/products \
  -H "Authorization: Bearer $SUBLIMEKEYS_API_KEY" \
  -d '{"slug":"my-app","key_prefix":"MYAPP"}'

2. Émettez une clé à chaque vente

curl -X POST https://api.sublimearts.io/v1/licenses \
  -H "Authorization: Bearer $SUBLIMEKEYS_API_KEY" \
  -d '{"product":"my-app","email":"buyer@mail.com","max_activations":3}'

→ {"key":"MYAPP-K3F7Q-9WZ2M-P8RT4-XN5CB", ...}
productrequis — le slug du produit de l'étape 1
emailoptionnel — affiché dans la liste des licences de votre tableau de bord
max_activationsoptionnel, 1 par défaut — sur combien de machine_id différents cette clé unique peut être active en même temps. Réglez-le selon ce que promet votre propre tarification (ex. 3 pour un forfait "usage personnel, 3 appareils"). Plafonné par votre forfait SublimeKeys, pas celui de votre client final — 5 en Free, 25 en Pro, 100 en Business (voir les tarifs).
expires_atoptionnel — date ISO ; omettez pour une clé à vie
notesoptionnel — texte libre, pour votre référence uniquement

Ou sautez cet appel entièrement — voir AUTOMATE plus bas.

3. Vérifiez dans votre app

Python — SDK officiel (recommandé)
# pip install sublimekeys
from sublimekeys import SublimeKeysClient

client = SublimeKeysClient(product_id="my-app")
result = client.activate(license_key=key)   # first run
result = client.verify(license_key=key)     # every launch after — offline-first,
                                             # verifies a signed lease locally,
                                             # zero network calls for up to 7 days
if result.valid:
    unlock_full_version()
Node.js / Electron — SDK officiel (recommandé)
// npm install sublimekeys
import { SublimeKeysClient } from "sublimekeys";

const client = new SublimeKeysClient("my-app");
const activated = await client.activate(key);     // first run
const result = await client.verify(key);          // every launch after — offline-first,
                                                   // verifies a signed lease locally,
                                                   // zero network calls for up to 7 days
if (result.valid) unlockFullVersion();

Pas sur Python ou Node.js, ou vous voulez appeler l'API brute vous-même ? SDK Python sur PyPI · SDK Node.js sur npm ou utilisez directement les endpoints ci-dessous.

Python — API brute
import requests

r = requests.post("https://api.sublimearts.io/activate", json={
    "license_key": key,
    "machine_id": machine_id,
    "product_id": "my-app",
})
if r.json()["valid"]:
    unlock_full_version()
Node.js — API brute
const r = await fetch("https://api.sublimearts.io/activate", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ license_key, machine_id, product_id: "my-app" }),
});
const { valid } = await r.json();
if (valid) unlockFullVersion();
cURL
curl -X POST https://api.sublimearts.io/activate \
  -d '{"license_key":"...","machine_id":"...","product_id":"my-app"}'
▸ Nouveau ici ? Où ces appels vont réellement dans votre app

L'exemple ci-dessus ne montre que /activate seul — dans une vraie app, vous appelez différents endpoints à différents moments :

L'app démarre
├─ Aucune clé de licence encore enregistrée (premier lancement)
│    → affichez votre écran "entrer la clé de licence"
│    → l'utilisateur la soumet → appelez /activate une fois → enregistrez le résultat localement
│
├─ Une clé de licence est déjà enregistrée (chaque lancement suivant)
│    → appelez /verify à la place (pas /activate à nouveau) — confirme
│      qu'elle est toujours valide sur cette machine
│
├─ API inaccessible (l'utilisateur est hors ligne)
│    → /activate et /verify renvoient tous deux un "bail" signé (valable 7 jours)
│    → vérifiez sa signature localement au lieu de faire aveuglément confiance au
│      dernier résultat — les SDK Python et Node.js le font automatiquement ; les
│      autres langages peuvent vérifier eux-mêmes la signature Ed25519 (clé publique
│      sur GET /public-key)
│
└─ L'utilisateur désinstalle / se déconnecte (optionnel)
     → appelez /deactivate pour que la place se libère pour une autre machine

Sur Python ou Node.js/Electron, les SDK officiels (PyPI · npm) gèrent déjà cela — y compris la vérification cryptographique réelle du bail hors ligne. La version brute ci-dessous saute cette étape (elle fait simplement confiance au dernier résultat enregistré hors ligne) — plus simple, mais non vérifiée cryptographiquement. Utilisez-la si vous n'êtes pas sur Python/Node.js ou si vous voulez un contrôle total.

Python — flux complet au démarrage de l'app (API brute, sans SDK)
import requests, json, os

STATE_FILE = "license_state.json"

def check_license(machine_id):
    saved = json.load(open(STATE_FILE)) if os.path.exists(STATE_FILE) else None

    try:
        if saved is None:
            # first run — ask the user for their key once
            key = prompt_for_license_key()
            r = requests.post("https://api.sublimearts.io/activate", json={
                "license_key": key, "machine_id": machine_id, "product_id": "my-app",
            }, timeout=5)
        else:
            # every later launch — re-check the saved key, don't ask again
            r = requests.post("https://api.sublimearts.io/verify", json={
                "license_key": saved["license_key"], "machine_id": machine_id, "product_id": "my-app",
            }, timeout=5)

        result = r.json()
        json.dump(result, open(STATE_FILE, "w"))
        return result["valid"]

    except requests.RequestException:
        # offline — trust the last known result instead of locking the user out
        return saved["valid"] if saved else False

Déjà à l'aise avec le concept ? Sautez ceci — les appels ci-dessus sont tout ce dont vous avez besoin.

SDKS OFFICIELS

🐍 Python — sublimekeys

Encapsule toute l'API et fait la vérification hors ligne pour vous — activate/verify/deactivate avec un bail signé vérifié localement, si bien que la plupart des démarrages ne font aucun appel réseau, plus des vérifications d'essai qui survivent aussi à une période hors ligne. Installe également une CLI sublimekeys pour tester une intégration depuis un terminal.

pip install sublimekeys
Voir sur PyPI →

⚡ Node.js / Electron — sublimekeys

Même conception capable de fonctionner hors ligne, zéro dépendance au runtime — la vérification Ed25519 utilise la crypto intégrée de Node, donc rien ne peut faire trébucher l'empaquetage asar d'Electron.

npm install sublimekeys
Voir sur npm →

D'autres langages sont sur la feuille de route. En attendant, chaque endpoint ci-dessous est un simple appel REST — appelez-le depuis tout ce qui peut faire une requête HTTPS.

RÉFÉRENCE DES ENDPOINTS — PUBLIC (appelé par votre app)

POST /activate

body : { "license_key", "machine_id", "product_id" }

▸ Détails

Premier lancement — lie une clé de licence à un machine_id. Peut être rappelé sans risque sur la même machine — ne consommera pas un autre emplacement d'activation. Renvoie valid:false avec un message si impossible (ex. limite d'activation atteinte sur une autre machine). En cas de succès, renvoie aussi un bail signé (fenêtre de confiance hors ligne de 7 jours) dans le champ lease de la réponse — le SDK Python le vérifie localement lors des lancements suivants plutôt que d'appeler l'API à chaque fois.

POST /verify

body : { "license_key", "machine_id", "product_id" }

▸ Détails

Chaque lancement suivant — confirme que la clé est toujours valide sur cette machine. Ne touche pas votre compteur d'activations, appelez-le donc aussi souvent que vous voulez. Renouvelle aussi le bail signé (voir /activate) à chaque appel réussi.

POST /deactivate

body : { "license_key", "machine_id", "product_id" }

▸ Détails

L'utilisateur se déconnecte / désinstalle — libère la place pour une autre machine.

POST /trial/start

body : { "machine_id", "product_id" }

▸ Détails

Récupère ou crée un essai de 7 jours pour une machine. Idempotent — réinstaller ne remet jamais le compteur à zéro.

POST /trial/status

body : { "machine_id", "product_id" }

▸ Détails

Vérification d'essai en lecture seule — n'en démarre jamais un.

Pas d'en-tête Authorization sur ceux-ci — la license_key elle-même est l'identifiant. L'API complète au niveau du compte (create/list/revoke) se trouve sous /v1/*, voir le tableau de bord.

⚡ AUTOMATE — LIVRAISON DE CLÉS SANS BACKEND

Sautez entièrement l'étape 2 ci-dessus. Pointez le webhook de votre prestataire de paiement vers l'URL de votre produit, et chaque vente émet une clé et l'envoie par email à votre acheteur — automatiquement.

  1. Tableau de bord Stripe → Developers → Webhooks → Add endpoint
  2. Collez l'URL de votre produit (connectez-vous et créez un produit pour obtenir la vôtre)
  3. Sélectionnez l'événement : checkout.session.completed
  4. Enregistrez. C'est tout — pas de serveur, pas de code.
  5. Optionnel mais recommandé : Stripe affiche un Signing secret juste après — collez-le dans "Signature verification" sur la page Produits, pour que nous rejetions tout ce qui ne vient pas vraiment de Stripe (pas seulement quiconque possède cette URL).

🔔 Vous voulez aussi recevoir un email à chaque vente ? Activez "Notify me" à côté de ce bloc sur la page Produits.

MIGRER DEPUIS GUMROAD, KEYGEN OU VOTRE PROPRE SERVEUR

Exportez vos clients existants dans un CSV avec une colonne email, puis exécutez ceci une fois par produit. Cela émet en masse une nouvelle clé SublimeKeys par ligne, préfixée avec votre marque.

migrate.py
import csv, os, requests

API_KEY = os.environ["SUBLIMEKEYS_API_KEY"]
PRODUCT = "my-app"

with open("customers.csv") as f:
    for row in csv.DictReader(f):
        r = requests.post("https://api.sublimearts.io/v1/licenses",
            headers={"Authorization": f"Bearer {API_KEY}"},
            json={"product": PRODUCT, "email": row["email"]})
        print(row["email"], "->", r.json()["key"])

Ceci émet des clés flambant neuves — cela ne préserve pas vos anciennes chaînes de clés (nous n'acceptons pas de valeurs de clé personnalisées, par conception). Envoyez par email à vos clients leur nouvelle clé, ou faites tourner les deux vérifications en parallèle dans votre app pendant une fenêtre de transition avant de retirer l'ancien système.

LIMITES DU FORFAIT

FREE

1 produit · 100 clés · 5 appareils/clé

PRO

5 produits · 1 000 clés · 25 appareils/clé

BUSINESS

produits et clés illimités · 100 appareils/clé

Atteindre une limite ne casse jamais les clés existantes — elles continuent à se vérifier pour toujours. Vous ne pouvez simplement plus en émettre de nouvelles tant que vous n'avez pas mis à niveau. Rétrograder ou annuler ne supprime non plus jamais rien.