Docs

Alles, was du brauchst, um SublimeKeys in deine App einzubauen. Kein Konto nötig, um es zu lesen.

$SUBLIMEKEYS_API_KEY

Jede Anfrage unten verwendet dies als Platzhalter für deinen echten Key. Anmelden (kostenlos, keine Karte nötig), um deinen zu bekommen und diese Beispiele mit deinem eigenen Produkt ausgefüllt zu sehen.

QUICKSTART — 3 AUFRUFE

1. Registriere dein Produkt (einmalig, unter Produkte)

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

2. Stelle bei jedem Verkauf einen Key aus

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", ...}
producterforderlich — der Produkt-Slug aus Schritt 1
emailoptional — wird in der Lizenzliste deines Dashboards angezeigt
max_activationsoptional, Standard ist 1 — auf wie vielen verschiedenen machine_ids dieser eine Key gleichzeitig aktiv sein kann. Setze es auf das, was dein eigenes Preismodell verspricht (z. B. 3 für ein "privater Gebrauch, 3 Geräte"-Paket). Begrenzt durch deinen SublimeKeys-Plan, nicht den deines Endkunden — 5 bei Free, 25 bei Pro, 100 bei Business (siehe Preise).
expires_atoptional — ISO-Datum; weglassen für einen lebenslangen Key
notesoptional — Freitext, nur zu deiner eigenen Referenz

Oder überspringe diesen Aufruf komplett — siehe AUTOMATE weiter unten.

3. Verifiziere innerhalb deiner App

Python — offizielles SDK (empfohlen)
# 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 — offizielles SDK (empfohlen)
// 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();

Nicht auf Python oder Node.js, oder möchtest du die rohe API selbst aufrufen? Python-SDK auf PyPI · Node.js-SDK auf npm oder nutze direkt die Endpunkte unten.

Python — rohe API
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 — rohe API
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"}'
▸ Neu dabei? Wo diese Aufrufe in deiner App tatsächlich hingehören

Das Beispiel oben zeigt nur /activate für sich allein — in einer echten App rufst du zu unterschiedlichen Zeitpunkten unterschiedliche Endpunkte auf:

App startet
├─ Noch kein Lizenzschlüssel gespeichert (erster Start)
│    → zeige deinen "Lizenzschlüssel eingeben"-Bildschirm
│    → Nutzer übermittelt ihn → rufe einmal /activate auf → speichere das Ergebnis lokal
│
├─ Ein Lizenzschlüssel ist bereits gespeichert (jeder spätere Start)
│    → rufe stattdessen /verify auf (nicht erneut /activate) — bestätigt,
│      dass er auf dieser Maschine noch gültig ist
│
├─ API nicht erreichbar (Nutzer ist offline)
│    → sowohl /activate als auch /verify geben einen signierten "Lease" zurück (7 Tage gültig)
│    → verifiziere seine Signatur lokal, statt dem letzten Ergebnis blind zu
│      vertrauen — die Python- und Node.js-SDKs tun dies automatisch; andere
│      Sprachen können die Ed25519-Signatur selbst verifizieren (öffentlicher
│      Schlüssel unter GET /public-key)
│
└─ Nutzer deinstalliert / meldet sich ab (optional)
     → rufe /deactivate auf, damit der Platz für eine andere Maschine frei wird

Auf Python oder Node.js/Electron übernehmen die offiziellen SDKs (PyPI · npm) das bereits — inklusive echter kryptografischer Verifizierung des Offline-Leases. Die rohe Version unten überspringt das (sie vertraut offline einfach dem zuletzt gespeicherten Ergebnis) — einfacher, aber nicht kryptografisch geprüft. Nutze sie, wenn du nicht auf Python/Node.js bist oder volle Kontrolle möchtest.

Python — vollständiger App-Start-Ablauf (rohe API, ohne 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

Schon vertraut mit dem Konzept? Überspringe das — die Aufrufe oben sind alles, was du brauchst.

OFFIZIELLE SDKS

🐍 Python — sublimekeys

Kapselt die gesamte API und übernimmt die Offline-Verifizierung für dich — activate/verify/deactivate mit einem lokal geprüften signierten Lease, sodass die meisten Starts keine Netzwerkaufrufe machen, plus Testphasen-Prüfungen, die auch eine Offline-Phase überstehen. Installiert außerdem eine sublimekeys-CLI zum Testen einer Integration vom Terminal aus.

pip install sublimekeys
Auf PyPI ansehen →

⚡ Node.js / Electron — sublimekeys

Gleiches offline-fähiges Design, null Laufzeit-Abhängigkeiten — die Ed25519-Verifizierung nutzt Node's eingebaute Krypto, sodass es für Electrons asar-Packaging nichts gibt, worüber es stolpern könnte.

npm install sublimekeys
Auf npm ansehen →

Weitere Sprachen sind auf der Roadmap. In der Zwischenzeit ist jeder Endpunkt unten ein einfacher REST-Aufruf — rufe ihn von allem aus auf, das eine HTTPS-Anfrage stellen kann.

ENDPUNKT-REFERENZ — ÖFFENTLICH (von deiner App aufgerufen)

POST /activate

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

▸ Details

Erster Start — bindet einen Lizenzschlüssel an eine machine_id. Sicher, auf derselben Maschine erneut aufzurufen — verbraucht keinen weiteren Aktivierungsplatz. Gibt valid:false mit einer Nachricht zurück, wenn es nicht geht (z. B. Aktivierungslimit auf einer anderen Maschine erreicht). Bei Erfolg wird zusätzlich ein signierter Lease (7-Tage-Offline-Vertrauensfenster) im lease-Feld der Antwort zurückgegeben — das Python-SDK verifiziert diesen bei späteren Starts lokal, statt jedes Mal die API aufzurufen.

POST /verify

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

▸ Details

Jeder nachfolgende Start — bestätigt, dass der Key auf dieser Maschine noch gültig ist. Berührt nicht deinen Aktivierungszähler, rufe es also so oft auf, wie du möchtest. Erneuert außerdem bei jedem erfolgreichen Aufruf den signierten Lease (siehe /activate).

POST /deactivate

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

▸ Details

Nutzer meldet sich ab / deinstalliert — gibt den Platz für eine andere Maschine frei.

POST /trial/start

body: { "machine_id", "product_id" }

▸ Details

Holt oder erstellt eine 7-tägige Testphase für eine Maschine. Idempotent — eine Neuinstallation setzt die Uhr nie zurück.

POST /trial/status

body: { "machine_id", "product_id" }

▸ Details

Nur lesende Testphasen-Prüfung — startet nie eine.

Kein Authorization-Header bei diesen — der license_key selbst ist die Anmeldeinformation. Die vollständige kontobezogene API (create/list/revoke) liegt unter /v1/*, siehe das Dashboard.

⚡ AUTOMATE — KEY-ZUSTELLUNG OHNE BACKEND

Überspringe Schritt 2 oben komplett. Richte den Webhook deines Zahlungsanbieters auf die URL deines Produkts, und jeder Verkauf stellt automatisch einen Key aus und mailt ihn deinem Käufer.

  1. Stripe-Dashboard → Developers → Webhooks → Add endpoint
  2. Füge die URL deines Produkts ein (melde dich an und erstelle ein Produkt, um deine zu bekommen)
  3. Wähle das Ereignis: checkout.session.completed
  4. Speichern. Das war's — kein Server, kein Code.
  5. Optional, aber empfohlen: Stripe zeigt direkt danach ein Signing secret — füge es auf der Produkte-Seite bei "Signature verification" ein, damit wir alles ablehnen, was nicht wirklich von Stripe kommt (nicht nur von jedem, der diese URL kennt).

🔔 Möchtest du bei jedem Verkauf auch selbst eine E-Mail bekommen? Aktiviere "Notify me" neben diesem Block auf der Produkte-Seite.

MIGRIERE VON GUMROAD, KEYGEN ODER DEINEM EIGENEN SERVER

Exportiere deine bestehenden Kunden in eine CSV mit einer email-Spalte und führe dies dann einmal pro Produkt aus. Es stellt pro Zeile einen frischen SublimeKeys-Lizenzschlüssel aus, mit dem Präfix deiner Marke.

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"])

Dies stellt brandneue Keys aus — es erhält deine alten Key-Strings nicht (wir akzeptieren bewusst keine benutzerdefinierten Key-Werte). Sende Kunden ihren neuen Key per E-Mail, oder lasse beide Prüfungen für ein Übergangsfenster parallel in deiner App laufen, bevor du das alte System abschaltest.

PLAN-LIMITS

FREE

1 Produkt · 100 Keys · 5 Geräte/Key

PRO

5 Produkte · 1.000 Keys · 25 Geräte/Key

BUSINESS

unbegrenzte Produkte & Keys · 100 Geräte/Key

Ein Limit zu erreichen bricht nie bestehende Keys — sie verifizieren für immer weiter. Du kannst nur keine neuen ausstellen, bis du upgradest. Downgrade oder Kündigung löschen ebenfalls nie etwas.