VAULT stellt zwei APIs bereit:
/api/verify.php) – für Anwendungen mit "einfachem" Lizenzmodell (Key + optionale IP-Bindung). Kein Token nötig./api/shop/issue.php) – für einen externen Webshop, der nach einem Kauf automatisch eine Lizenz anlegen soll. Erfordert ein Bearer-Token (siehe Admin → Shop-API-Tokens).Anwendungen mit dem Lizenzmodell UPSec (signierte, Ed25519-basierte Token mit verschlüsseltem PHP-Quellcode) werden offline durch die UPSec-PHP-Extension geprüft – dafür ist kein API-Aufruf nötig, siehe Abschnitt "UPSec" unten.
POST https://vault.upower24.com/api/verify.php
Content-Type: application/json
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
key | string | ja | Der Lizenzschlüssel, z.B. XXXX-XXXX-XXXX-XXXX |
app | string | ja | Slug der Anwendung (in der Verwaltung hinterlegt) |
Die anfragende IP-Adresse wird serverseitig automatisch aus der Verbindung ermittelt (kein Parameter nötig). Ist beim Schlüssel eine IP-Bindung hinterlegt, muss diese mit der anfragenden IP übereinstimmen.
curl -X POST https://vault.upower24.com/api/verify.php \
-H "Content-Type: application/json" \
-d '{"key":"AB12-CD34-EF56-GH78","app":"mein-app-slug"}'
HTTP 200 bei gültigem Schlüssel, sonst HTTP 403. Immer JSON:
{
"valid": true,
"reason": "ok",
"application": "mein-app-slug",
"expires_at": null
}
Bei ungültigem Schlüssel:
{
"valid": false,
"reason": "invalid_key"
}
reason-Werte| Wert | Bedeutung |
|---|---|
ok | Schlüssel gültig |
invalid_key | Schlüssel unbekannt/falsch |
revoked | Schlüssel wurde gesperrt |
expired | Ablaufdatum überschritten |
ip_mismatch | Anfragende IP passt nicht zur hinterlegten IP-Bindung |
unknown_app | App-Slug existiert nicht oder ist inaktiv |
missing_parameters | key oder app fehlt |
$ch = curl_init('https://vault.upower24.com/api/verify.php');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'key' => 'AB12-CD34-EF56-GH78',
'app' => 'mein-app-slug',
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if (!empty($response['valid'])) {
// Anwendung starten
}
import requests
r = requests.post(
"https://vault.upower24.com/api/verify.php",
json={"key": "AB12-CD34-EF56-GH78", "app": "mein-app-slug"},
timeout=10,
)
data = r.json()
if data.get("valid"):
... # Anwendung starten
POST https://vault.upower24.com/api/shop/issue.php
Header: Authorization: Bearer <API-Token> (erzeugt unter Admin → Shop-API-Tokens)
Content-Type: application/json
Legt bei einem Verkauf automatisch eine Lizenz an (für beide Lizenzmodelle, je nach hinterlegtem Modell der Anwendung), ordnet sie einem Kunden zu (wird per E-Mail angelegt, falls noch nicht vorhanden) und verschickt die Lizenz-Mail. Der Webshop selbst ist nicht Teil von VAULT.
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
application | string | ja | Slug der Anwendung |
customer.email | string | ja | Kunde wird per E-Mail gefunden oder neu angelegt |
customer.name | string | nein | Nur bei Neuanlage relevant |
ip_restriction | string | nein | Nur bei Lizenzmodell "Einfach" |
bnd_host | string | nein | Nur bei Lizenzmodell "UPSec" |
expires_at | string | nein | Format YYYY-MM-DD |
order_reference | string | nein | Bestell-/Auftragsnummer des Shops, zur Zuordnung |
send_mail | bool | nein | Standard true |
curl -X POST https://vault.upower24.com/api/shop/issue.php \
-H "Authorization: Bearer <API-Token>" \
-H "Content-Type: application/json" \
-d '{
"application": "mein-app-slug",
"customer": {"email": "kunde@example.com", "name": "Max Mustermann"},
"expires_at": "2027-01-01",
"order_reference": "SHOP-10234"
}'
Antwort (201):
{
"success": true,
"license_id": 42,
"customer_id": 7,
"key": "AB12-CD34-EF56-GH78",
"mail_sent": true,
"mail_error": null
}
Fehlerantwort, z.B. bei unbekannter Anwendung oder ungültigem Token:
{ "success": false, "error": "invalid_token" }
Für Anwendungen mit Lizenzmodell UPSec liefert VAULT keinen einfachen Schlüssel, sondern
einen signierten Token im Format UPSEC1.<payload>.<signatur>, der den
(verschlüsselt eingebetteten) Content-Key für den jeweils verschlüsselten .upsecc-Container
enthält. Die Prüfung erfolgt offline durch die beim Kunden installierte UPSec-PHP-Extension
(Ed25519-Signaturprüfung mit dem Vault-Public-Key, der in der Extension einkompiliert ist) – es ist kein
Netzwerkzugriff zur Laufzeit nötig.
Ablauf: Anwendung mit upsec-encrypt.php verschlüsseln → Content-Key in VAULT bei der
Anwendung hinterlegen → pro Kunde über VAULT (Admin-UI oder Shop-API) einen Token ausstellen → Token
als .upsecl-Datei an den Kunden übergeben.
POST https://vault.upower24.com/api/upsec/status.php
Content-Type: application/json
UPSec-Lizenzen werden zur Laufzeit offline geprüft. Damit ausgegebene Lizenzen dennoch
gesperrt werden können, kann die Extension zusätzlich periodisch diesen Endpoint abfragen.
Die Antwort ist selbst Ed25519-signiert (Format UPSECR1.<payload>.<signatur>),
sodass sie von einem Angreifer weder gefälscht noch (dank Nonce + Zeitstempel) wiederholt eingespielt
werden kann. Aktiviert wird der Check in der php.ini der Anwendung über
upsec.revoke_url.
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
token | string | ja | Der vollständige UPSec-Token (UPSEC1.…) |
nonce | string | ja | Zufälliger Wert (base64url, 16–64 Zeichen); wird in der signierten Antwort zurückgegeben (Replay-Schutz) |
Antwort (200): roher Text (das signierte Status-Token), Payload-Felder:
h = sha256(token), st = ok|revoked|expired|unknown,
ts = Serverzeit (unix), nc = echoter Nonce, ttl = empfohlene Grace-Sekunden.
curl -X POST https://vault.upower24.com/api/upsec/status.php \
-H "Content-Type: application/json" \
-d '{"token":"UPSEC1.eyJ...","nonce":"Zm9vYmFyYmF6cXV4MTIz"}'
Extension-Verhalten: Bei Status ok läuft die Anwendung und die signierte Antwort wird
lokal zwischengespeichert. Bei revoked/expired/unknown wird sofort gesperrt. Ist der Server
nicht erreichbar, gilt die letzte gültige Freigabe bis zum Ablauf der Grace-Period
(upsec.revoke_grace). Mit upsec.revoke_interval wird der Server höchstens
einmal pro Intervall kontaktiert (nicht bei jedem Seitenaufruf).