First-run experience
The first time a user launches your app, they need to enter a license key. Make this frictionless:Desktop apps
Show a clean, focused dialog. Don’t overwhelm with options — just a single input field and an activate button.- Auto-format the input as the user types (add dashes automatically).
- Accept keys with or without dashes.
- Show a “Purchase” link for users who don’t have a key yet.
- Trim whitespace — users often copy keys with trailing spaces.
CLI tools
Support multiple input methods to minimize friction:Storing the key locally
After successful validation, save the key locally so users don’t re-enter it on every launch.Settings page
Provide a settings or “About” page where users can see their license status:| Field | Value |
|---|---|
| License key | A3K9-****-****-QHDT (partially masked) |
| Status | Active |
| Plan | Pro |
| Expires | December 31, 2026 |
| Devices | 1 of 2 slots used |
| [Deactivate] |
- Mask the license key (show first and last groups only).
- Show the expiry date prominently.
- Include a “Deactivate” button that clears the stored key and returns to the license dialog.
- If using license variables, show the plan tier.
Expiration and renewal
When a license is approaching expiration, show gentle reminders:Trial mode
Use the Developer API to issue time-limited trial licenses:Upgrade prompts
When a user on a lower tier tries to use a gated feature, show a helpful prompt instead of silently failing:Graceful degradation
If your app has a free tier or limited mode, fall back to it instead of killing the app entirely:Error messages
Always show user-friendly messages. Map internal error codes to helpful text:| Error | User sees |
|---|---|
invalid_key | ”Invalid license key. Please check and try again.” |
expired | ”Your license has expired. [Renew now]“ |
revoked | ”This license has been deactivated. Contact support.” |
hwid_mismatch | ”This license is in use on another device. Contact support to transfer.” |
no_credits | ”Service temporarily unavailable. Please try again in a few minutes.” |
| Network error | ”Couldn’t connect to the license server. Check your internet connection.” |
no_credits or invalid_app to end users.