Validate
POST
/{tenantId}/{productId}/validate Re-checks an activated instance and returns a fresh lease. The SDK calls this periodically and on launch. Uses the common headers & path parameters.
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
license_key | string | yes | The license key |
instance_id | string | yes | The instance_id returned by activate |
app_version / sdk_version / platform | string | no | Telemetry |
curl -X POST https://api.keylight.dev/acme/notes/validate \ -H "Content-Type: application/json" \ -H "X-Keylight-SDK-Key: $KEYLIGHT_SDK_KEY" \ -d '{ "license_key": "ACME-XXXX-XXXX-XXXX-XXXX", "instance_id": "5f7e7b9a-1c2d-4e3f-9a8b-7c6d5e4f3a2b" }'// kl from the activate example; the instance_id is persisted by the SDKconst res = await kl.validate();// res.valid, res.leaseResponse (200)
Section titled “Response (200)”{ "valid": true, "license_expires_at": null, "lease": { "kid": "k1", "status": "active", "entitlements": ["pro"], "...": "…" }}A time-limited license past its expiry but configured to fall back (not hard-expire) returns 200 with valid: false and a lease whose status is "fallback".
License expired (422)
Section titled “License expired (422)”A hard-expired license returns a signed expired lease so the SDK can update local state at once:
{ "valid": false, "error": "License expired", "lease": { "kid": "k1", "status": "expired", "...": "…" }}Errors
Section titled “Errors”| Status | Condition |
|---|---|
400 | Invalid JSON body |
401 | Missing / invalid SDK key |
403 | Tenant state blocks validation |
404 | Tenant / product / license not found |
422 | License revoked, or instance not found / deactivated |
429 | Quota exceeded |
500 | Tenant not fully configured |
Suspended tenants can still validate by design — active apps keep rotating leases through the grace window so end users aren’t disrupted.