Skip to content

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.

FieldTypeRequiredDescription
license_keystringyesThe license key
instance_idstringyesThe instance_id returned by activate
app_version / sdk_version / platform / sdkstringnoTelemetry. platform is the operating system (macos, windows, linux, ios, …), or the runtime (web, workers) where no OS applies; sdk is which SDK is reporting (swift, rust, js, csharp, cpp)
Terminal window
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"
}'
{
"valid": true,
"license_expires_at": null,
"lease": { "kid": "k1", "status": "active", "entitlements": ["pro"], "...": "…" },
"free_tier_enabled": true,
"trial_duration_days": 14,
"kid": "k1",
"issued_at": 1788671279,
"expires_at": 1788757679,
"signature": "base64…"
}

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".

Every validate response — including the valid: false and expired ones — carries the settings your dashboard owns, so a licensed install learns them without a second request.

FieldTypeDescription
free_tier_enabledbooleanAlways present.
trial_duration_daysnumberAbsent when the tenant has never configured one — keep your own default. 0 means trials are off. Absent and 0 are different values, not one falsy case.
kid / issued_at / expires_at / signatureThe signature over the two settings above. Present whenever trial_duration_days is.

The envelope is byte-identical to the one GET /config returns, and the rules for checking it are the same — verify the signature, including the one that matters most: a present trial_duration_days must carry a valid signature, or you ignore it. Verify-if-present is not a check.

Note the two signatures in this response are independent and cover different things: the lease is signed over entitlement, and this envelope is signed over the settings. Neither stands in for the other.

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", "...": "…" }
}
StatusCondition
400Invalid JSON body
401Missing / invalid SDK key
403Tenant state blocks validation
404Tenant / product / license not found
422License revoked, or instance not found / deactivated
429Quota exceeded
500Tenant 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.