Migrating to Keylight
You already have customers. This guide is about moving them onto Keylight without breaking what they paid for.
There are two situations, and they call for different moves.
Two paths
Section titled “Two paths”Your old app can’t ship an update. The old build has its own licensing and never calls Keylight — so nothing you do in Keylight can break it. You bring your customers into Keylight so the customer portal can offer them the move to your new version. The old build keeps running on its own until customers upgrade or drift away.
Your app is shipping a new version. Import your existing customers as they are, so their current key validates in the new build — no re-issuing, no re-delivery. Their app activates that key once (the customer enters it, or your code reads it from your old storage); see How an imported customer activates below.
How an imported customer activates
Section titled “How an imported customer activates”Importing creates the license on Keylight’s servers. It does not place anything on the customer’s device — a customer who bought before Keylight has no cached lease yet. That lease is minted the first time their key is activated against Keylight (manager.activate(key:)), after which it validates offline like any other license. So the imported key has to reach the SDK once. There are three ways, differing only in how much app code you write:
| Route | App code | Customer sees |
|---|---|---|
| Customer enters the key once | None — your existing LicensePromptView | A one-time activation prompt |
| Silent shim | A few lines | Nothing |
| Claim a legacy key | None — hosted portal | Visits a page, gets a key by email |
Customer enters it once. Ship the new build with the activation UI you already integrated. The returning customer pastes the key they own; it validates because you imported it. No migration code, no repurchase — the floor that always works.
Silent shim. If your old build kept the raw key somewhere your new build can read, read it on first launch and activate it yourself, so the customer sees nothing:
if case .licensed = manager.licenseState { // already migrated — nothing to do} else if let legacyKey = UserDefaults.standard.string(forKey: "licenseKey") { // ^ YOUR old storage — NOT a KeylightSDK call. Swap in your own read // (plist, a file, your old Keychain item). Only your app knows it. try? await manager.activate(key: legacyKey) // ← this IS the SDK call}This works only when (a) the old key is readable on the device and (b) you imported with that same key string (the license_key column), so the server record matches.
Claim a legacy key. Customer-driven and zero app code, but it mints a fresh key rather than preserving the old one. A good fit for a frozen app whose key you can’t read anyway.
Example: shipping a major version
Section titled “Example: shipping a major version”Say you’ve sold v1 through v14 over the years, and v15 is going out.
- Import the old keys. Upload your customer list — see Bulk import. Each imported license is tagged Migrated, so you can see your backlog at a glance.
- Offer the upgrade. Turn on an Upgrade to your v15 key type. v1 holders are offered the move from the portal.
- Let the old versions fade. They keep running on their own; customers come over on their own schedule.
Choosing how to import
Section titled “Choosing how to import”| You want to… | Use |
|---|---|
| Pre-load your whole base from a list you already have | Bulk import |
| Let customers migrate themselves from an old vendor, verified one at a time | Claim a legacy key |
| Handle a big base, missing keys, or messy data | Email support@keylight.dev |
Bulk import is developer-driven: you hand Keylight a CSV and every customer lands at once. Claim is customer-driven: each customer enters their old key and email at a portal page, Keylight verifies it, and mints them a fresh key. Use whichever fits how much you want to drive.
What to know going in
Section titled “What to know going in”- Bulk import can only keep a customer’s existing key if you still have the plaintext key to put in the CSV. No key on file? Import by email and Keylight generates one.
- Claim mints a fresh key — it does not preserve the old key string.
- A frozen old build keeps working only because it runs its own validation, not Keylight’s. Importing its customers doesn’t touch that build; it sets up their move to the new one.
Not sure which path is yours? Email support@keylight.dev and we’ll help you plan the transition.