רישיונות
ניהול אימות רישיונות, הפעלה ומעקב אחר מכשירים.
429 Too Many Requests עם הכותרת Retry-After: 60 עד שהחלון מתאפס.אימות רישיון
אימות והפעלה של מפתח רישיון. נקודת קצה זו מוגבלת ל-5 בקשות לדקה לכל כתובת IP.
נקודת קצה: POST /api/licenses/validate
| פרמטר | סוג | חובה | תיאור |
|---|---|---|---|
license_key | string | כן | מפתח הרישיון לאימות |
device_id | string | כן | מזהה יציב וייחודי של המכשיר שמופעל. יש לשלוח את אותו ערך בכל פעם עבור מכשיר נתון, באמצעותו המכשיר תופס את העמדה שלו ותופס אותה מחדש |
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?;
תגובה (הצלחה):
{
"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
}
}
תגובה (שגיאה):
{
"statusCode": 400,
"statusMessage": "Invalid licence key or validation failed"
}
| סטטוס | מתי |
|---|---|
400 | license_key או device_id חסרים, ריקים או ארוכים מדי, או שהמפתח אינו מוכר, אינו פעיל או שתוקפו פג |
409 | כל העמדות ברישיון כבר תפוסות על ידי מכשירים אחרים, ואף אחד מהם לא היה במצב סרק מספיק זמן כדי שניתן יהיה להשיב את העמדה |
429 | חריגה ממגבלת הקצב, ראו הגבלת קצב |
400 לעולם אינה מציינת איזה שדה גרם לשגיאה, ויש לוודא ש-license_key וגם device_id קיימים ואינם ריקים לפני ניסיון חוזר.ביטול הפעלת רישיון
נדרש אימות זהותנדרשת עוגיית ההתחברות session_token של בעל הרישיון (ראו אימות זהות), וניתן לבטל את ההפעלה רק של רישיון שבבעלותכם.
ביטול הפעלה של רישיון במכשיר מסוים או בכל המכשירים.
נקודת קצה: POST /api/licenses/deactivate
| פרמטר | סוג | חובה | תיאור |
|---|---|---|---|
license_key | string | כן | מפתח הרישיון לביטול ההפעלה |
device_id | string | לא | מכשיר מסוים לביטול ההפעלה (יש להשמיט כדי לבטל בכל המכשירים) |
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?;
תגובה:
{
"success": true,
"message": "Device deactivated successfully",
"deactivated_count": 1,
"remaining_activations": 4
}
remaining_activations הוא מספר העמדות שעדיין בשימוש לאחר ביטול ההפעלה, כלומר מספר המכשירים הייחודיים שנותרו פעילים ברישיון. זה אינו מספר העמדות הפנויות. לכן ביטול ההפעלה בכל המכשירים מחזיר 0. את מספר העמדות הפנויות יש לחשב כ-activation_limit - remaining_activations, באמצעות activation_limit מתוך GET /api/licenses/status. ללא device_id ההודעה היא "All devices deactivated successfully"; deactivated_count הוא מספר העמדות שקריאה זו שחררה.סטטוס רישיון
נדרש אימות זהותנדרשת עוגיית ההתחברות session_token של בעל הרישיון (ראו אימות זהות), וניתן לבדוק רק רישיון שבבעלותכם.
בדיקת הסטטוס הנוכחי של רישיון. מוגבל ל-30 בקשות לדקה לכל כתובת IP.
נקודת קצה: GET /api/licenses/status
| פרמטר | סוג | חובה | תיאור |
|---|---|---|---|
license_key | query | כן | מפתח הרישיון לבדיקה |
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?;
תגובה:
{
"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"
}
]
}
מחזור החיים של רישיון
הגבלת קצב
נקודות הקצה של הרישיונות מוגבלות בקצב לכל כתובת IP בחלון קבוע של 60 שניות. בתגובת 429 מוחזרת כותרת אחת:
| כותרת | תיאור |
|---|---|
Retry-After | מספר השניות עד שהחלון מתאפס (תמיד 60) |
מגבלות קצב לפי נקודת קצה
| נקודת קצה | בקשות / 60 שניות | רמה |
|---|---|---|
/api/licenses/validate | 5 | מחמירה |
/api/licenses/status | 30 | רגילה |
/api/licenses/deactivate | 30 | רגילה |
POST /api/licenses/validate מחילה את המגבלה המחמירה פעמיים: פעם אחת לכל כתובת IP, ופעם נוספת לפי ה-license_key שנשלח, כך שלא ניתן להפציץ מפתח יחיד מכתובות IP רבות.
429 Too Many Requests למשך יתרת חלון 60 השניות. אין משך חסימה מדורג או הולך ומחמיר.סוגי רישיונות
כל רישיון משויך לאחת מרמות התוכניות הנוכחיות. מערך התכונות והמגבלות המחייב לכל רמה הוא זה שמוצג בדף התמחור, ראו השוואת תוכניות.
| רמה | למי היא מיועדת | תוספות בולטות לעומת הרמה שמתחתיה |
|---|---|---|
free | תוכנית חינמית קבועה, ללא כרטיס אשראי, ללא תפוגה | שלט למצגות פשוט: חדר אחד, מציג אחד, שיתוף מסך עם סימן מים ו-Stream Deck; כל שאר התכונות נעולות |
presenter | מציגים | Timer Pro, צ'אט, ציור, ריבוי מארחים ו-NDI |
pro (Studio HD) | מפיקים עצמאיים | משתתפים מתקשרים, חדרים מותאמים אישית, שיתוף וידאו וכלי הבסיס של Studio |
ultra (Studio 4K) | משתמשים מתקדמים ומשדרים | חדרים ללא הגבלה, ערכות צבעי מותג שמורות, שכבות, הקלטת ISO, שידור חוזר ומערך הכלים הרחב של Studio |
studio (Studio 8K) | צוותי הפקה | מעצב פריסת חדרים, מיתוג white label, ה-Client API, מפתחות API, דומיינים מותאמים אישית, רישיונות צוות משותפים לפי עמדה |
enterprise | ארגונים גדולים ומחלקות רכש | SSO, SCIM ותפקידי צוות מותאמים אישית, חוזים שנתיים לפי עמדה |