Sign in

Licences

Licence validation, activation, and device management API

Manage licence validation, activation, and device tracking.

Rate Limiting: Licence endpoints are rate-limited per IP over a fixed 60-second window. Exceeding the limit returns 429 Too Many Requests with a Retry-After: 60 header until the window resets.

Validate Licence

Validate and activate a licence key. This endpoint is rate-limited to 5 requests per minute per IP address.

Endpoint: POST /api/licenses/validate

ParameterTypeRequiredDescription
license_keystring
Yes
Licence key to validate
device_idstring
Yes
Stable, unique identifier for the device being activated. Send the same value every time for a given device, it is what claims and re-claims that device's seat
curl -X POST "$BASE_URL/api/licenses/validate" \
  -H "Content-Type: application/json" \
  -d '{"license_key":"XXXX-XXXX-XXXX-XXXX","device_id":"device_abc123"}'

Response (Success):

{
  "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
  }
}

Response (Error):

{
  "statusCode": 400,
  "statusMessage": "Invalid licence key or validation failed"
}
StatusWhen
400license_key or device_id is missing, empty or over-long, or the key is unknown, inactive or expired
409Every seat on the licence is already held by another device, and none was idle long enough to reclaim
429Rate limit exceeded, see Rate Limiting
For security, all licence validation errors return the same generic message to prevent enumeration attacks. A 400 therefore never says which field was at fault, confirm both license_key and device_id are present and non-empty before retrying.

Deactivate Licence

Authentication Required

Requires the session_token session cookie of the licence owner (see Authentication), you can only deactivate a licence you own.

Deactivate a licence from a specific device or all devices.

Endpoint: POST /api/licenses/deactivate

ParameterTypeRequiredDescription
license_keystring
Yes
Licence key to deactivate
device_idstring
No
Specific device to deactivate (omit for all devices)
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"}'

Response:

{
  "success": true,
  "message": "Device deactivated successfully",
  "deactivated_count": 1,
  "remaining_activations": 4
}
Despite its name, remaining_activations is the number of seats still in use after the deactivation, that is, the count of distinct devices left active on the licence. It is not the number of free seats. Deactivating all devices therefore returns 0. Compute free seats as activation_limit - remaining_activations, using activation_limit from GET /api/licenses/status. Without device_id the message reads "All devices deactivated successfully"; deactivated_count is the number of seats this call released.

Licence Status

Authentication Required

Requires the session_token session cookie of the licence owner (see Authentication), you can only inspect a licence you own.

Check the current status of a licence. Rate-limited to 30 requests per minute per IP.

Endpoint: GET /api/licenses/status

ParameterTypeRequiredDescription
license_keyquery
Yes
Licence key to check
curl -X GET "$BASE_URL/api/licenses/status?license_key=XXXX-XXXX-XXXX-XXXX" \
  -b cookies.txt

Response:

{
  "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": "Ultra", "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"
    }
  ]
}

Licence Lifecycle

Rate Limiting

Licence endpoints are rate-limited per IP over a fixed 60-second window. On a 429, one header is returned:

HeaderDescription
Retry-AfterSeconds until the window resets (always 60)

Rate Limits by Endpoint

EndpointRequests / 60sTier
/api/licenses/validate5Strict
/api/licenses/status30Standard
/api/licenses/deactivate30Standard

POST /api/licenses/validate applies the Strict limit twice: once per IP, and once keyed on the submitted license_key, so a single key cannot be hammered from many IPs.

Exceeding a limit returns 429 Too Many Requests for the remainder of the 60-second window. There is no progressive or escalating block duration.

Licence Types

A licence resolves to one of the current plan tiers. The authoritative feature and limit set for each tier is what the pricing page renders, see Compare plans.

TierWho it is forNotable additions over the tier below
freePermanent free plan, no card, no expiryA simple clicker: one room, one presenter, watermarked screen sharing and Stream Deck; every other feature is locked
presenterPresentersTimer Pro, chat, drawing, multi-host and NDI
pro (Pro)Solo producersCallers, custom rooms, video sharing and the Studio essentials
ultra (Max)Power users and streamersUnlimited rooms, saved brand colour themes, layers, ISO recording, replay and the wider Studio toolset
studio (Ultra)Production teamsRoom layout designer, whitelabel branding, the Client API, API keys, custom domains, pooled per-seat team licences
enterpriseLarge orgs and procurementSSO, SCIM and custom team roles, per-seat annual contracts
Older licences may still carry legacy product names. Those keep the entitlements they were bought with, and the API resolves them onto the tiers above.