Offene Lizenz-API-Dokumentation
v1.0
Offene Lizenz-API-Dokumentation
Dieses Dokument richtet sich an Entwickler, die den Ablauf „Zahlung → Ausstellung → Aktivierung → Verifizierung“ in ihre eigene Software integrieren möchten (Client-Software / reine Vertriebsprodukte). Jede API wird mit Aufrufzeitpunkt, Anfrageparametern, Antwortfeldern und Fehlercodes beschrieben.
1. Grundkonzepte
| Konzept | Feld / Begriff | Beschreibung |
|---|---|---|
| Software-API-Geheimnis | licenseApiSecret |
Wird automatisch erzeugt, wenn das Produkt die „Lizenzaktivierung“ aktiviert. Im Produktbearbeitungsformular im Entwicklerzentrum einsehbar. Ihr Softwareserver berechnet damit die HMAC-Signatur, die Plattform verifiziert damit. Nur auf Ihrem Server speichern, niemals im Client einbetten. |
| Lizenzcode | licenseCode |
Ein von der Plattform erzeugter eindeutiger Code. Benutzer aktivieren damit Ihre Software. |
| Maschinencode | machineCode |
Eine vom Client erzeugte Gerätekennung (pro Computer eindeutig; stabilen Maschinen-Fingerabdruck hashen, mindestens 8 Zeichen). |
| Aktivierungstoken | activationToken |
Wird von der Plattform bei Aktivierung / Ausstellung ausgestellt. Die Software speichert ihn und sendet ihn bei jeder Startprüfung zurück. |
| Bestell-ID | clientOrderId |
Die Bestell-ID der In-Software-Zahlung (vom Client oder Server erzeugt). Die Plattform dedupliziert über „Produkt + Bestell-ID“, um doppelte Abbuchungen und doppelte Ausstellung zu verhindern. |
2. Vorbereitung
- Aktivieren Sie beim Veröffentlichen des Produkts die „Lizenzaktivierung“ und speichern Sie das erzeugte Software-API-Geheimnis (licenseApiSecret);
- Konfigurieren Sie im Veröffentlichungsformular die Editionsliste (z. B. BASIC/PRO/ULTIMATE) und die Upgrade-Strategie (SAME_CODE = Upgrade mit gleichem Code / NEW_CODE = neuen Code ausstellen);
- Speichern Sie das Geheimnis auf Ihrem Softwareserver; der Client hält nur Lizenzcode und Aktivierungstoken.
3. API-Übersicht
Basispfad: https://www.powersoftware.app/frontApi (für lokale / Testumgebungen durch Ihre Bereitstellungsdomain ersetzen).
| API | Aufrufzeitpunkt | Authentifizierung | Signatur |
|---|---|---|---|
POST /license/software/generate |
Direkt nach erfolgreicher In-Software-Zahlung | Keine (Signaturprüfung) | Erforderlich |
POST /license/software/upgrade |
Direkt nach erfolgreicher Verlängerungs- / Editions-Upgrade-Zahlung | Keine (Signaturprüfung) | Erforderlich |
POST /license/activate |
Erste Aktivierung durch den Benutzer / Gerätewechsel | Keine | Nicht erforderlich |
POST /license/verify |
Bei jedem Start der Software | Keine | Nicht erforderlich |
POST /license/deactivate |
Benutzer hebt Bindung des alten Geräts auf (Profilbereich) | Anmeldung | Nicht erforderlich |
4. Signaturregeln (erforderlich für generate / upgrade)
Signaturtext: Fügen Sie die folgenden Felder in genau dieser Reihenfolge mit Zeilenumbrüchen (\n) zusammen (fehlende optionale Felder mit Leerwerten: edition leere Zeichenkette, expiryDays = 0):
productId \n machineCode \n edition \n expiryDays \n clientOrderId \n licenseCode \n timestamp
Signatur: HMAC-SHA256(Software-API-Geheimnis licenseApiSecret, Signaturtext), Base64URL-kodiert, in das Feld signature eintragen.
Replay-Schutz: timestamp ist ein Zeitstempel in Millisekunden. Die Plattform verlangt eine Abweichung von höchstens 5 Minuten zur Serverzeit, sonst wird signatureInvalid zurückgegeben.
Node.js-Beispiel:
const crypto = require("crypto");
const payload = [productId, machineCode, edition, expiryDays, clientOrderId, licenseCode, timestamp].join("\n");
const signature = crypto.createHmac("sha256", API_SECRET).update(payload).digest("base64url");
Python-Beispiel:
import hashlib, hmac, base64
payload = "\n".join([str(productId), machineCode, edition, str(expiryDays), clientOrderId, licenseCode, str(timestamp)])
signature = base64.urlsafe_b64encode(hmac.new(API_SECRET.encode(), payload.encode(), hashlib.sha256).digest()).decode().rstrip("=")
(Base64URL ist Standard-Base64, bei dem + durch -, / durch _ ersetzt und die =-Auffüllung am Ende entfernt wird.)
5. API-Details
5.1 Lizenzcode erzeugen (nach In-Software-Zahlung aufrufen)
Aufrufzeitpunkt: Direkt nach Abschluss einer In-Software-Zahlung ruft Ihr Server die API einmal auf und speichert Lizenzcode und Aktivierungstoken. Dieselbe Bestellung soll nur einmal gesendet werden; Wiederholungen sind idempotent und führen nicht zu einer zweiten Ausstellung.
POST /license/software/generate
Anfrageparameter (JSON-Body):
| Parameter | Typ | Pflicht | Quelle | Beschreibung |
|---|---|---|---|---|
| productId | number | Ja | Fest verdrahtet / Server-Konfiguration | Produkt-ID, passend zum auf der Plattform veröffentlichten Produkt |
| machineCode | string | Ja | Client erzeugt | Maschinencode des aktuellen Geräts, mindestens 8 Zeichen |
| edition | string | Nein | Bei Zahlung vom Client gewählt | Editionskennung; muss in der Editionsliste des Produkts stehen; Standard ist die erste Edition |
| expiryDays | number | Nein | Bei Zahlung vom Client gewählt | Gültigkeitsdauer in Tagen, 0 = dauerhaft; Bereich 0-3650 |
| clientOrderId | string | Ja | Client / Server erzeugt | Bestell-ID der In-Software-Zahlung, 1-64 Zeichen; Idempotenzschlüssel |
| timestamp | number | Ja | Server erzeugt | Zeitstempel in Millisekunden |
| signature | string | Ja | Server berechnet | HMAC-Signatur, mindestens 10 Zeichen |
Antwortfelder von content:
| Feld | Typ | Beschreibung |
|---|---|---|
| licenseId | number | ID des Lizenzdatensatzes |
| licenseCode | string | Der Lizenzcode (in Ihre Lizenzdaten schreiben) |
| productId | number | Produkt-ID |
| edition | string | Editionskennung |
| machineId | number | ID des gebundenen Maschinendatensatzes |
| activatedAt | string | Aktivierungszeit (ISO8601) |
| expiryTime | string/null | Ablaufzeit (ISO8601), null = dauerhaft |
| maxMachines | number | Maximale Anzahl bindbarer Maschinen |
| activationToken | string | Aktivierungstoken; für die Startprüfung speichern |
Antwortbeispiel:
{
"code": "SUCCESS",
"requestId": "xxx",
"success": true,
"content": {
"licenseId": 1001,
"licenseCode": "AB12-CD34-EF56-GH78",
"productId": 88,
"edition": "PRO",
"machineId": 2001,
"activatedAt": "2026-08-05T10:00:00.000Z",
"expiryTime": "2027-08-05T10:00:00.000Z",
"maxMachines": 1,
"activationToken": "eyJhbGciOiJIUzI1NiJ9..."
}
}
Fehlercodes dieser API: productIdRequired, machineCodeInvalid, orderIdRequired, productNotFound, productNotEnabled, apiSecretMissing, signatureInvalid, orderAlreadyUsed.
5.2 Edition upgraden / verlängern (nach Zahlung aufrufen)
Aufrufzeitpunkt: Nach Abschluss einer Zahlung für Verlängerung oder Editions-Upgrade. Dieselbe Bestellung soll nur einmal gesendet werden.
POST /license/software/upgrade
Anfrageparameter (JSON-Body):
| Parameter | Typ | Pflicht | Quelle | Beschreibung |
|---|---|---|---|---|
| productId | number | Ja | Fest verdrahtet / Server-Konfiguration | Produkt-ID |
| licenseCode | string | Ja | In der Software gespeichert | Aktueller Lizenzcode, mindestens 10 Zeichen |
| machineCode | string | Nein | Client erzeugt | Aktueller Maschinencode; bei Bindungsmigration (NEW_CODE) oder zusätzlicher Bindung angeben |
| edition | string | Ja | Bei Zahlung vom Client gewählt | Ziel-Editionskennung |
| expiryDays | number | Nein | Bei Zahlung vom Client gewählt | Zusätzliche Gültigkeitsdauer in Tagen, 0 = dauerhaft; Bereich 0-3650 |
| clientOrderId | string | Ja | Client / Server erzeugt | Bestell-ID dieses Kaufs; Idempotenzschlüssel |
| timestamp | number | Ja | Server erzeugt | Zeitstempel in Millisekunden |
| signature | string | Ja | Server berechnet | HMAC-Signatur |
Verarbeitungsstrategie (durch Produktkonfiguration bestimmt):
- SAME_CODE (Upgrade mit gleichem Code): Der Lizenzcode bleibt gleich, Maschinenbindungen bleiben gültig, die Gültigkeit wird verlängert (dauerhaft bleibt dauerhaft). Die Antwort enthält zusätzlich
upgraded: true; - NEW_CODE (neuen Code ausstellen): Der alte Code wird gesperrt, ein neuer Code wird ausgestellt und die Maschinenbindungen werden migriert. Die Antwort enthält zusätzlich
oldLicenseId, undlicenseCodeist der neue Code.
Antwortfelder von content: wie in 5.1, zusätzlich upgraded: true; bei NEW_CODE zusätzlich oldLicenseId (ID des alten Lizenzdatensatzes; der alte Code ist bereits gesperrt).
Fehlercodes dieser API: productIdRequired, licenseCodeRequired, orderIdRequired, productNotFound, productNotEnabled, apiSecretMissing, signatureInvalid, codeNotFound, revoked, orderAlreadyUsed, editionRequired.
5.3 Lizenz aktivieren (erste Aktivierung / neues Gerät)
Aufrufzeitpunkt: Nachdem der Benutzer einen Lizenzcode erhalten hat (Selbstausstellung, Verwaltungsausstellung usw.) und ihn auf der Aktivierungsseite der Client-Software eingibt. Beim Gerätewechsel auf dem neuen Gerät aufrufen.
POST /license/activate
Anfrageparameter (JSON-Body):
| Parameter | Typ | Pflicht | Quelle | Beschreibung |
|---|---|---|---|---|
| licenseCode | string | Ja | Benutzereingabe | Lizenzcode, mindestens 10 Zeichen |
| machineCode | string | Ja | Client erzeugt | Maschinencode des aktuellen Geräts, mindestens 8 Zeichen |
Antwortfelder von content: wie in 5.1 (licenseId, licenseCode, productId, edition, machineId, activatedAt, expiryTime, maxMachines, activationToken).
Hinweise:
- Ein Lizenzcode kann an mehrere Maschinen gebunden werden, begrenzt durch
maxMachines(Standard aus Produktkonfiguration); - Erneutes Aktivieren derselben Maschine nutzt die bestehende Bindung und stellt ein neues Aktivierungstoken aus (idempotent);
- Fehlgeschlagene Aktivierungen werden pro IP + Lizenzcode begrenzt; zu viele Fehlversuche ergeben
tooManyAttempts.
Fehlercodes dieser API: codeNotFound, revoked, expired, machineLimit, tooManyAttempts.
5.4 Lizenz verifizieren (bei jedem Start)
Aufrufzeitpunkt: Bei jedem Start der Software (oder vor dem Entsperren von Funktionen). Die Software muss das von 5.1 / 5.2 / 5.3 zurückgegebene activationToken speichern.
POST /license/verify
Anfrageparameter (JSON-Body):
| Parameter | Typ | Pflicht | Quelle | Beschreibung |
|---|---|---|---|---|
| licenseCode | string | Ja | In der Software gespeichert | Lizenzcode, mindestens 10 Zeichen |
| machineCode | string | Ja | Client erzeugt | Maschinencode des aktuellen Geräts, mindestens 8 Zeichen |
| activationToken | string | Ja | Von der Plattform ausgestellt, von der Software gespeichert | Aktivierungstoken, mindestens 20 Zeichen |
Antwortfelder von content:
| Feld | Typ | Beschreibung |
|---|---|---|
| valid | boolean | Immer true (Fehler werden als Fehlercodes zurückgegeben) |
| licenseId | number | ID des Lizenzdatensatzes |
| productId | number | Produkt-ID |
| edition | string | Aktuelle Editionskennung |
| expiryTime | string/null | Ablaufzeit (ISO8601), null = dauerhaft |
Hinweise:
- Verifizierungsergebnisse werden ca. 60 Sekunden zwischengespeichert; Schreiboperationen (Sperren, Bindung aufheben, Upgrade) invalidierten den Cache sofort, Verzögerungen sind also kein Thema;
- Die Software sollte
expiryTimeprüfen und nach Ablauf das Entsperren von Funktionen beenden.
Fehlercodes dieser API: tokenInvalid, machineNotActivated, invalidOrRevoked, expired, tooManyAttempts.
5.5 Gerätebindung aufheben (vor Gerätewechsel, Anmeldung erforderlich)
Aufrufzeitpunkt: Der Benutzer hebt die Bindung des alten Geräts unter „Profilbereich → Meine Lizenzen“ auf und aktiviert anschließend auf dem neuen Gerät über 5.3.
POST /license/deactivate
Anfrageparameter (JSON-Body):
| Parameter | Typ | Pflicht | Quelle | Beschreibung |
|---|---|---|---|---|
| licenseCode | string | Ja | Lizenzliste des Benutzers | Lizenzcode, mindestens 10 Zeichen |
| machineCode | string | Ja | Lizenzliste des Benutzers | Der aufzuhebende Maschinencode, mindestens 8 Zeichen |
Antwortfelder von content: true.
Hinweise:
- Nur der Eigentümer der Lizenz (Käufer oder Benutzer, der den gebundenen Maschinencode registriert hat) kann dies ausführen;
- Aufhebe-Kontingent: Standardmäßig kann dieselbe Lizenz innerhalb von 30 Tagen nur einmal aufgehoben werden (im Verwaltungsbereich konfigurierbar); bei Überschreitung wird
unbindQuotaExceededzurückgegeben.
Fehlercodes dieser API: noPermission, machineNotBound, unbindQuotaExceeded.
6. Fehlercodes
Geschäftsfehler werden einheitlich zurückgegeben (tip enthält eine lesbare Meldung):
{
"code": "BUSINESS_WARNING",
"requestId": "xxx",
"success": false,
"errorMessage": "LICENSE_GENERATE_FAILED",
"tip": "Signature verification failed"
}
Fehler bei der Parameterprüfung ergeben code: "PARAM_VALIDATE_FAILED" und die konkrete Feldmeldung in tip.
| Fehlercode | Bedeutung |
|---|---|
productNotEnabled |
Das Produkt hat die Lizenzaktivierung nicht aktiviert |
apiSecretMissing |
Für das Produkt ist kein Software-API-Geheimnis (licenseApiSecret) konfiguriert |
signatureInvalid |
Signaturprüfung fehlgeschlagen (Geheimnis falsch, Reihenfolge des Signaturtexts falsch oder Zeitstempel außerhalb des Fensters) |
machineCodeInvalid |
Maschinencode ungültig (kürzer als 8 Zeichen) |
orderAlreadyUsed |
Diese Bestellung hat bereits einen Lizenzcode erzeugt (Idempotenzkonflikt: mit anderem Maschinencode wiederholt) |
codeNotFound |
Lizenzcode nicht gefunden |
revoked |
Lizenzcode wurde gesperrt oder ist unbrauchbar |
expired |
Lizenzcode ist abgelaufen |
invalidOrRevoked |
Lizenz ist bei der Verifizierung ungültig oder gesperrt |
machineNotActivated |
Diese Maschine ist nicht aktiviert |
tokenInvalid |
Aktivierungstoken ungültig |
machineLimit |
Die Obergrenze gebundener Maschinen ist erreicht |
machineNotBound |
Diese Maschine ist nicht gebunden |
noPermission |
Keine Berechtigung für diese Lizenz |
unbindQuotaExceeded |
Die Lizenz kann innerhalb von 30 Tagen nur einmal aufgehoben werden; später erneut versuchen |
tooManyAttempts |
Zu viele Versuche; später erneut versuchen |
productNotFound |
Produkt nicht gefunden |
editionRequired |
Bitte die Zieledition wählen |
7. Typische Abläufe
- In-Software-Zahlungsschleife: Zahlung erfolgreich →
software/generate(liefert Lizenzcode + Aktivierungstoken) → Software speichert beides → bei jedem Startverify→ Funktionen entsperren; Verlängerung / Upgrade →software/upgrade; - Selbstausstellung / Verwaltungsausstellung: Ein Lizenzcode wird im Entwicklerzentrum oder in der Verwaltung erzeugt → der Benutzer erhält den Code → im Client
activate, um das Gerät zu binden und das Token zu erhalten → beim Startverify; - Gerätewechsel: Altes Gerät über
deactivateim Profilbereich entbinden → auf dem neuen Gerätactivate→verify; - Unterschied der Upgrade-Strategie: SAME_CODE behält den gleichen Code; NEW_CODE stellt einen neuen Code aus (alter Code gesperrt, Maschinenbindungen werden automatisch migriert).
8. Hinweise
- Geheimnis nur serverseitig: Die Signatur darf nur auf Ihrem Softwareserver erstellt werden; gelangt das Geheimnis in den Client, ist das Lizenzsystem wirkungslos;
- Stabilität des Maschinencodes: Verwenden Sie einen stabilen Maschinen-Fingerabdruck und hashen Sie ihn; ändert sich der Maschinencode nach einer Neuinstallation, erst entbinden, dann erneut aktivieren;
- Idempotenz: Machen Sie
clientOrderIdglobal eindeutig (z. B. Zeitstempel + Zufallswert); Wiederholungen führen nicht zu doppelter Ausstellung; - Cache:
verify-Ergebnisse werden ca. 60 Sekunden gecacht und durch Schreiboperationen sofort invalidiert; - Ratenbegrenzung: Fehlgeschlagene Aktivierungen / Verifizierungen werden begrenzt; der Client sollte Fehlermeldungen und Wiederholungsabstände angemessen umsetzen;
- Vertrauen Sie der Plattformantwort: Gültigkeit, Edition und Maschinenobergrenzen werden von der Plattform bestimmt; lockern Sie diese auf Softwareseite nicht selbst.