Skip to main content
Migrate Already selling? Move your customers to Keylight without re-issuing a single key.
Keylight

Feature

Built-in free trials

Set a trial length once; the SDK tracks the countdown and reports days remaining. No trial server, no separate trial keys.

Start Free
SDK-managed Days-left state Clean conversion
Fixed-length trial
Set trialDurationDays once at startup; the SDK runs the evaluation period.
Days-remaining state
licensing.state reports .trial(daysLeft:) so your UI can nudge at the right moment.
No trial backend
The trial runs without a Stripe payment and without a separate trial-key system.
Seamless conversion
When the customer pays, the Stripe webhook issues a real license and the state flips to .licensed.

Updated March 2026

Why trials belong in the licensing layer

Most paid desktop apps sell on a try-before-you-buy basis — a customer downloads the app, uses it for a couple of weeks, and decides. That evaluation period is a licensing state, not a marketing afterthought: while the trial runs, the app must unlock its paid features; when it ends, it must stop.

If trials live outside your licensing system, you end up building a parallel mechanism — a trial timer, trial-only keys, separate expiry logic — that has to stay consistent with the real licensing it eventually hands off to. Keylight treats the trial as a first-class licensing state instead, so the same SDK that handles paid licenses handles the trial, and the handoff between them is seamless.

Setting a trial length

You set the trial when you create the SDK manager, with trialDurationDays:

import KeylightSDK

let licensing = try! Keylight.manager(
    sdkKey: "sdk_live_...",
    tenantId: "acme",
    productId: "myapp",
    keyPrefix: "ACME",
    trustedPublicKeyBase64: "<your-public-key>",
    trialDurationDays: 14,
    branding: .init(appName: "My App", purchaseURL: URL(string: "https://acme.example.com/buy")!, supportEmail: "[email protected]", tintColor: .blue)
)

That single value defines the evaluation window. The SDK begins the trial on first launch and tracks the countdown — there is no trial server to run and no trial-only key to mint and later swap out.

Reading the trial state

The trial surfaces through the same licensing.state your app already switches on:

await licensing.checkOnLaunch()

switch licensing.state {
case .licensed:
    enablePaidFeatures()
case .trial(let daysLeft):
    enablePaidFeatures()
    showTrialBanner(daysLeft: daysLeft)
case .expired:
    showRenewalPrompt()
case .invalid:
    showActivationSheet()
}

During the trial, state is .trial(daysLeft:) and your app unlocks its paid features exactly as it would for a paying customer — the point of a trial is to show the real product. The daysLeft value lets you place a gentle banner and make it more prominent as the window narrows. When the trial runs out, state becomes .expired and you show a renewal or purchase prompt.

Because the trial is just another state case, you do not write separate UI paths — the same switch handles trial, licensed, and expired.

Converting a trial to a paid license

When a customer decides to buy, they go through your Stripe checkout. Stripe fires checkout.session.completed, Keylight mints an Ed25519-signed license, and delivers it. The next time the SDK resolves, it finds the real license and state flips from .trial or .expired to .licensed.

The conversion is clean because the trial and the paid license were always the same system. There is no migration of trial data, no reconciling a trial account with a purchase — the customer simply moves from one state case to another. See Stripe integration for how the payment becomes a license, and license keys for how that license is signed.

Choosing a trial length

Keylight does not prescribe a trial length — trialDurationDays is yours to set — but the common range is 7 to 30 days. Shorter trials create urgency and tend to convert evaluators faster; longer trials suit apps a customer needs to fold into a real workflow before they can judge them. A 14-day trial is a reasonable default for most productivity and developer tools. Whatever you choose, the SDK enforces it identically.

Trials are included on every Keylight plan — see Pricing, starting at $19/month. For how trials feel inside a direct-sold Mac app, see licensing for macOS apps.

Frequently asked

How do free trials work in Keylight?+

You set a trial length in days when you create the SDK manager. The SDK tracks the evaluation period locally and reports the days remaining through licensing.state.

Does a trial need a Stripe payment?+

No. The trial runs with no payment. A Stripe payment happens when the customer converts, at which point Keylight issues a real signed license.

Start licensing your app today

Drop in the Swift SDK, point it at your dashboard, and sell paid apps in under a minute. Free forever tier included.

Start Free