Lizenzen
Verwalten Sie Lizenzvalidierung, Aktivierung und Geräteverfolgung.
429 Too Many Requests mit dem Header Retry-After: 60 zurückgegeben, bis das Fenster zurückgesetzt wird.Lizenz validieren
Validiert und aktiviert einen Lizenzschlüssel. Dieser Endpunkt ist auf 5 Anfragen pro Minute pro IP-Adresse begrenzt.
Endpunkt: POST /api/licenses/validate
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
license_key | string | Ja | Zu validierender Lizenzschlüssel |
device_id | string | Ja | Stabile, eindeutige Kennung für das zu aktivierende Gerät. Senden Sie für ein bestimmtes Gerät jedes Mal denselben Wert, denn damit wird der Lizenzplatz dieses Geräts belegt und erneut beansprucht |
curl -X POST "$BASE_URL/api/licenses/validate" \
-H "Content-Type: application/json" \
-d '{"license_key":"XXXX-XXXX-XXXX-XXXX","device_id":"device_abc123"}'
interface LicenseValidation {
valid: boolean
license: {
id: string
status: string
product: object
activation_date: string
expiration_date: string
current_activations: number
}
}
const result: LicenseValidation = await $fetch('/api/licenses/validate', {
method: 'POST',
body: {
license_key: 'XXXX-XXXX-XXXX-XXXX',
device_id: 'device_abc123'
}
})
import requests
response = requests.post(
"$BASE_URL/api/licenses/validate",
json={
"license_key": "XXXX-XXXX-XXXX-XXXX",
"device_id": "device_abc123"
}
)
result = response.json()
package main
import (
"bytes"
"encoding/json"
"net/http"
)
func validateLicense() {
payload := map[string]string{
"license_key": "XXXX-XXXX-XXXX-XXXX",
"device_id": "device_abc123",
}
body, _ := json.Marshal(payload)
resp, _ := http.Post(
"$BASE_URL/api/licenses/validate",
"application/json",
bytes.NewBuffer(body),
)
defer resp.Body.Close()
}
<?php
$response = file_get_contents(
'$BASE_URL/api/licenses/validate',
false,
stream_context_create([
'http' => [
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => json_encode([
'license_key' => 'XXXX-XXXX-XXXX-XXXX',
'device_id' => 'device_abc123'
])
]
])
);
$result = json_decode($response, true);
use reqwest::Client;
use serde_json::json;
let client = Client::new();
let response = client
.post("$BASE_URL/api/licenses/validate")
.json(&json!({
"license_key": "XXXX-XXXX-XXXX-XXXX",
"device_id": "device_abc123"
}))
.send()
.await?;
Antwort (Erfolg):
{
"valid": true,
"license": {
"id": "uuid",
"status": "active",
"product": { "id": "uuid", "name": "studio", "features": ["client_api", "api_keys"] },
"activation_date": "2024-01-01T00:00:00Z",
"expiration_date": "2025-12-31T23:59:59Z",
"current_activations": 1
}
}
Antwort (Fehler):
{
"statusCode": 400,
"statusMessage": "Invalid licence key or validation failed"
}
| Status | Wann |
|---|---|
400 | license_key oder device_id fehlt, ist leer oder zu lang, oder der Schlüssel ist unbekannt, inaktiv oder abgelaufen |
409 | Alle Lizenzplätze sind bereits durch andere Geräte belegt, und keiner war lange genug ungenutzt, um neu vergeben zu werden |
429 | Ratenlimit überschritten, siehe Ratenbegrenzung |
400 verrät daher nie, welches Feld fehlerhaft war: Prüfen Sie vor einem erneuten Versuch, ob license_key und device_id vorhanden und nicht leer sind.Lizenz deaktivieren
Authentifizierung erforderlichErfordert das Session-Cookie session_token des Lizenzinhabers (siehe Authentifizierung). Sie können nur Lizenzen deaktivieren, die Ihnen gehören.
Deaktivieren Sie eine Lizenz auf einem bestimmten Gerät oder auf allen Geräten.
Endpunkt: POST /api/licenses/deactivate
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
license_key | string | Ja | Zu deaktivierender Lizenzschlüssel |
device_id | string | Nein | Bestimmtes Gerät, das deaktiviert werden soll (weglassen für alle Geräte) |
curl -X POST "$BASE_URL/api/licenses/deactivate" \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{"license_key":"XXXX-XXXX-XXXX-XXXX","device_id":"device_abc123"}'
const result = await $fetch('/api/licenses/deactivate', {
method: 'POST',
// session cookie (session_token) is sent automatically same-origin
body: {
license_key: 'XXXX-XXXX-XXXX-XXXX',
device_id: 'device_abc123'
}
})
import requests
response = requests.post(
"$BASE_URL/api/licenses/deactivate",
headers={"Cookie": f"session_token={token}"},
json={
"license_key": "XXXX-XXXX-XXXX-XXXX",
"device_id": "device_abc123"
}
)
req, _ := http.NewRequest("POST",
"$BASE_URL/api/licenses/deactivate",
bytes.NewBuffer(body))
req.Header.Set("Cookie", "session_token="+token)
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
<?php
$response = file_get_contents(
'$BASE_URL/api/licenses/deactivate',
false,
stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\n" .
"Cookie: session_token=$token",
'content' => json_encode([
'license_key' => 'XXXX-XXXX-XXXX-XXXX',
'device_id' => 'device_abc123'
])
]
])
);
let response = client
.post("$BASE_URL/api/licenses/deactivate")
.header("Cookie", format!("session_token={}", token))
.json(&json!({
"license_key": "XXXX-XXXX-XXXX-XXXX",
"device_id": "device_abc123"
}))
.send()
.await?;
Antwort:
{
"success": true,
"message": "Device deactivated successfully",
"deactivated_count": 1,
"remaining_activations": 4
}
remaining_activations die Anzahl der Lizenzplätze an, die nach der Deaktivierung noch belegt sind, also die Anzahl der verschiedenen Geräte, die auf der Lizenz aktiv bleiben. Es ist nicht die Anzahl der freien Plätze. Das Deaktivieren aller Geräte liefert daher 0. Berechnen Sie die freien Plätze als activation_limit - remaining_activations, mit activation_limit aus GET /api/licenses/status. Ohne device_id lautet die Meldung „All devices deactivated successfully“; deactivated_count ist die Anzahl der Lizenzplätze, die dieser Aufruf freigegeben hat.Lizenzstatus
Authentifizierung erforderlichErfordert das Session-Cookie session_token des Lizenzinhabers (siehe Authentifizierung). Sie können nur Lizenzen einsehen, die Ihnen gehören.
Prüfen Sie den aktuellen Status einer Lizenz. Begrenzt auf 30 Anfragen pro Minute pro IP.
Endpunkt: GET /api/licenses/status
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
license_key | query | Ja | Zu prüfender Lizenzschlüssel |
curl -X GET "$BASE_URL/api/licenses/status?license_key=XXXX-XXXX-XXXX-XXXX" \
-b cookies.txt
const status = await $fetch('/api/licenses/status', {
// session cookie (session_token) is sent automatically same-origin
query: { license_key: 'XXXX-XXXX-XXXX-XXXX' }
})
import requests
response = requests.get(
"$BASE_URL/api/licenses/status",
headers={"Cookie": f"session_token={token}"},
params={"license_key": "XXXX-XXXX-XXXX-XXXX"}
)
req, _ := http.NewRequest("GET",
"$BASE_URL/api/licenses/status?license_key=XXXX-XXXX-XXXX-XXXX",
nil)
req.Header.Set("Cookie", "session_token="+token)
resp, _ := http.DefaultClient.Do(req)
<?php
$response = file_get_contents(
'$BASE_URL/api/licenses/status?license_key=XXXX-XXXX-XXXX-XXXX',
false,
stream_context_create([
'http' => [
'header' => "Cookie: session_token=$token"
]
])
);
let response = client
.get("$BASE_URL/api/licenses/status")
.header("Cookie", format!("session_token={}", token))
.query(&[("license_key", "XXXX-XXXX-XXXX-XXXX")])
.send()
.await?;
Antwort:
{
"license": {
"id": "uuid",
"license_key": "XXXX-XXXX-XXXX-XXXX",
"status": "active",
"purchase_date": "2024-01-01T00:00:00Z",
"activation_date": "2024-01-01T00:00:00Z",
"expiration_date": "2025-12-31T23:59:59Z",
"days_until_expiration": 365,
"activation_limit": 5,
"current_activations": 2,
"available_activations": 3,
"is_expired": false,
"is_active": true,
"product": { "id": "uuid", "name": "Studio 8K", "description": "...", "features": [] },
"user": { "id": "uuid", "first_name": "Jane", "last_name": "Doe", "email": "user@example.com" }
},
"active_devices": [
{
"id": "uuid",
"device_id": "device_abc123",
"device_name": "Studio Mac",
"platform": "macos",
"app_version": "3.1.2",
"activated_at": "2024-01-01T00:00:00Z",
"last_seen_at": "2024-01-02T09:00:00Z",
"ip_address": "192.168.1.1"
}
]
}
Lizenz-Lebenszyklus
Ratenbegrenzung
Lizenz-Endpunkte sind pro IP über ein festes 60-Sekunden-Fenster ratenbegrenzt. Bei einem 429 wird ein Header zurückgegeben:
| Header | Beschreibung |
|---|---|
Retry-After | Sekunden bis zum Zurücksetzen des Fensters (immer 60) |
Ratenlimits nach Endpunkt
| Endpunkt | Anfragen / 60 s | Stufe |
|---|---|---|
/api/licenses/validate | 5 | Streng |
/api/licenses/status | 30 | Standard |
/api/licenses/deactivate | 30 | Standard |
POST /api/licenses/validate wendet das strenge Limit zweimal an: einmal pro IP und einmal bezogen auf den übermittelten license_key, sodass ein einzelner Schlüssel nicht von vielen IPs aus massenhaft angefragt werden kann.
429 Too Many Requests zurückgegeben. Es gibt keine progressive oder eskalierende Sperrdauer.Lizenztypen
Eine Lizenz wird einer der aktuellen Tarifstufen zugeordnet. Maßgeblich für die Funktionen und Limits jeder Stufe ist das, was die Preisseite anzeigt, siehe Tarife vergleichen.
| Stufe | Zielgruppe | Wichtige Ergänzungen gegenüber der Stufe darunter |
|---|---|---|
free | Dauerhaft kostenloser Tarif, keine Karte, kein Ablaufdatum | Ein einfacher Presenter: ein Raum, ein(e) Vortragende(r), Bildschirmfreigabe mit Wasserzeichen und Stream Deck; alle anderen Funktionen sind gesperrt |
presenter | Vortragende | Timer Pro, Chat, Zeichnen, Multi-Host und NDI |
pro (Studio HD) | Solo-Produzenten | Anrufer, eigene Räume, Videofreigabe und die Studio-Grundfunktionen |
ultra (Studio 4K) | Power-User und Streamer | Unbegrenzte Räume, gespeicherte Farbthemen für Ihre Marke, Ebenen, ISO-Aufnahme, Replay und der erweiterte Studio-Werkzeugkasten |
studio (Studio 8K) | Produktionsteams | Raumlayout-Designer, Whitelabel-Branding, die Client API, API-Schlüssel, eigene Domains, gepoolte Team-Lizenzen pro Platz |
enterprise | Große Organisationen und Beschaffung | SSO, SCIM und benutzerdefinierte Teamrollen, Jahresverträge pro Platz |