Swift API
The Swift SDK exposes a small public surface. The full reference for each symbol lives on a dedicated page; this page is the index.
Entry points
Section titled “Entry points”Keylight.manager(sdkKey:tenantId:productId:keyPrefix:trustedPublicKeyBase64:trialDurationDays:branding:kid:freeTierEnabled:maxOfflineDays:storage:requireSignedConfig:)— the one-call factory. Decodes the public key, buildsKeylightConfiguration,KeylightProvider, andLicenseManagerfor you. This is what 99% of consumers use.KeylightConfiguration(sdkKey:tenantId:productId:keyPrefix:trialDurationDays:trustedPublicKeys:keychainServicePrefix:fileStoragePolicy:branding:storeKitProductId:maxOfflineDays:)— the long-form constructor. Reach for it when you need to customizemaxOfflineDays, supply multiple keys for rotation, override the keychain service prefix, or set astoreKitProductIdfor the StoreKit fallback path.
Core types
Section titled “Core types”| Symbol | Purpose | Reference |
|---|---|---|
LicenseManager | @MainActor ObservableObject driving app state. Read manager.isEntitled, manager.state, manager.currentLicenseExpiresAt, manager.currentEntitlements. | Keylight.manager |
KeylightProvider | The HTTP client for /activate, /validate, /deactivate. Conforms to LicenseProvider. Wraps the SDK key, retry/backoff, and Ed25519 verification. | Validation & revalidation |
LicensePromptView | SwiftUI view rendering the activation/deactivation/trial UI on all five Apple platforms. | Paywall view |
BrandingConfig | App name, purchase URL, support email, tint color used by LicensePromptView. | Keylight.manager |
LicenseState | .trial(daysRemaining:), .licensed, .expired, .invalid. | License lifecycle |
KeylightError | Typed errors from activateLicense, validateLicense, deactivateLicense. | Error handling |
Notification.Name.keylightLicenseDidChange | Posted after every state transition. | Keylight.manager |
Important methods
Section titled “Important methods”manager.checkOnLaunch()— call once at app start.manager.refreshIfNeeded()— call from.onChange(of: scenePhase)when the app becomes.active. Debounced.manager.activate(key:)— drive your own activation UI.LicensePromptViewcalls this for you.manager.deactivate()— release the instance slot.manager.hasEntitlement(_:)— check whether the current lease grants a named feature flag.manager.isValidKeyFormat(_:)— cheap pre-flight format check before callingactivate.manager.effectiveTrialDurationDays()— the trial length actually in force: the dashboard’s value if the server has sent one, otherwise the value you compiled in. 0.11.0+manager.effectiveFreeTierEnabled()— whether the free tier is on, resolved the same way. 0.11.0+manager.fetchConfig()— ask the server for the settings now, instead of waiting for the nextvalidateor beacon to carry them. Nothing calls this for you. 0.11.0+manager.refreshAfterUpgrade(timeout:pollInterval:)— pollvalidatebriefly after a purchase and returntrueas soon as the entitlements or state change. Seconds; defaults 30 and 2. See After a purchase.
Configuration knobs worth knowing
Section titled “Configuration knobs worth knowing”trialDurationDays— set onKeylight.manager(...). Since 0.11.0 this is the seed, not the final word: it is what a brand-new install uses before it has ever reached the server, after which the dashboard’s Trial length wins. Keep setting it — dropping it would make first launch depend on the network.0still means no trial. Read the value actually in force witheffectiveTrialDurationDays().requireSignedConfig— defaultfalse. Verify the Ed25519 signature on the dashboard-owned settings before caching them. Turn it on only once your app has a trial length set in the dashboard. 0.12.1+ on the factory. See Verify that the settings really came from your dashboard.maxOfflineDays— default15, only configurable via the long-formKeylightConfigurationconstructor. Hard cap on time since last successful online check; see Offline leases.keychainServicePrefix— auto-derived as<tenantId>.<productId>.keylight.devbyKeylight.manager(...). Override via the long-form constructor only if you need a stable Keychain identity across a rename.trustedPublicKeys: [String: Curve25519.Signing.PublicKey]— the long-form constructor accepts akid → keymap so you can ship multiple keys side-by-side during rotation. The factory decodes a single base64 key and registers it underkid = "k1".
What’s not public
Section titled “What’s not public”LicenseDO, KeychainHelper, the lease wire format internals, and the retry/backoff machinery are intentionally internal. They aren’t part of the SemVer contract and can change between minor versions.