Skip to content

HTTP API

The Swift SDK talks to three public endpoints. You can also call them directly if you’re integrating from a non-Swift platform.

All three:

  • Are scoped /<tenant-id>/<product-id>/<action>.
  • Require an X-Keylight-SDK-Key header (see SDK key).
  • Accept and return JSON.
  • Are hard-gated by your monthly API-call quota. When exceeded, Keylight returns 429 with a Retry-After header.

Registers a new instance of a license and returns a signed Ed25519 lease. Called by the SDK the first time a license key is entered.

HeaderRequiredValue
Content-Typeyesapplication/json
X-Keylight-SDK-Keyyes (once tenant has set one)Full SDK key string
{
"license_key": "ACME-XXXX-XXXX-XXXX-XXXX",
"instance_name": "Nicolas's MacBook Pro"
}
  • license_key - the raw license key the customer pasted in. Keylight normalizes it server-side.
  • instance_name - a human-readable device label shown in the dashboard. The SDK sends ProcessInfo.processInfo.hostName by default.
{
"activated": true,
"instance_id": "5f7e7b9a-...",
"lease": {
"kid": "primary",
"licenseKeyHash": "4e7a...",
"instanceId": "5f7e7b9a-...",
"issuedAt": 1713546000,
"expiresAt": 1714150800,
"status": "active",
"signature": "MEQCIB..."
}
}

The instance_id is Keylight-issued - store it alongside the license key. You’ll send it back on every subsequent /validate or /deactivate call.

StatusCondition
400Invalid JSON body
401Missing or invalid X-Keylight-SDK-Key
402Plan instance limit reached (hard cap)
403Tenant lifecycle state does not allow activation (e.g. suspended, pending_verification)
404Tenant / product / license key not found
422Missing required field; license key expired
429Monthly API-call quota exceeded (returns Retry-After header)

If the same license key is re-activated from the same device, Keylight detects the reactivation and returns the existing instance_id without consuming a new activation slot.

Refreshes a lease for an already-activated instance. Called periodically by the SDK.

{
"license_key": "ACME-XXXX-XXXX-XXXX-XXXX",
"instance_id": "5f7e7b9a-..."
}
{
"valid": true,
"lease": { "kid": "primary", "...": "..." }
}

Unlike other errors, expiry returns a signed expired lease so the SDK can update local state immediately:

{
"valid": false,
"error": "License expired",
"lease": { "kid": "primary", "status": "expired", "...": "..." }
}
StatusCondition
401Missing / invalid SDK key
403Tenant lifecycle state blocks validation
404Tenant / product / license key / license record not found
422License revoked, instance deactivated, or instance not found
429Quota exceeded

Suspended tenants can still validate by design - already-active apps keep rotating leases through the grace window so end users aren’t disrupted. See Billing & plans.

Releases an instance slot so the license can be activated on another device.

{
"license_key": "ACME-XXXX-XXXX-XXXX-XXXX",
"instance_id": "5f7e7b9a-..."
}
{ "deactivated": true }
StatusCondition
401Missing / invalid SDK key
404Tenant / product / license key not found
422Instance already deactivated or not found

Every activate and validate response includes a lease object. The lease is Ed25519-signed by Keylight and verified offline by the SDK.

FieldTypeMeaning
kidstringKey ID in your app’s trusted-keys map
licenseKeyHashhex stringSHA-256 of the normalized license key
instanceIdUUIDThe activation this lease is bound to
issuedAtunix secondsWhen Keylight signed
expiresAtunix secondsissuedAt + 7 days
statusstring"active" or "expired"
entitlementsstring[]Sorted feature strings granted to this instance (may be empty)
signaturebase64Ed25519 over v3|kid|keyHash|instanceId|issuedAt|expiresAt|status|entitlements_csv

entitlements_csv is the entitlements array sorted and comma-joined (empty string when there are no entitlements). Sorting is required so the client and server reconstruct an identical payload regardless of the order in which entitlements were added on either side.

Signature verification rules and the rationale for the 7-day TTL are covered in Ed25519 leases.

  • Monthly API calls - hard quota per plan; 429 with Retry-After once exceeded. Counters reset at the start of each calendar month.
  • Instance cap - hard per-plan cap on concurrent active instances. /activate returns 402 when exceeded.
  • License count - soft 100k ceiling per account; enforced at mint time, not at activation.

Plan quotas are listed on Billing & plans.