How to Launch a Mac App Outside the App Store — Keylight blog<br>Skip to main content<br>Migrate<br>Already selling? Move your customers to Keylight without re-issuing a single key.<br>→
Sign In<br>Start Free
← Blog<br>macos distribution licensing launch<br>How to Launch a Mac App Outside the App Store<br>May 23, 2026 · 7 min read · Nicolas Demanez — Founder<br>If you’ve already decided to skip the Mac App Store, the question shifts from should I? to what are the actual steps? This post is the playbook. If you’re still in the decision phase — weighing commission, discovery, and customer ownership — start with how to sell a Mac app outside the App Store and come back here when you’re ready to ship.
Below are the six steps to take a finished Mac app from your build folder to a launched product with paying customers.
Step 1: Sign and notarize with Developer ID
macOS will not cleanly open an app that isn’t signed by an identified developer and notarized by Apple. This is non-negotiable — without it, your customers see a “cannot be opened because the developer cannot be verified” warning, and most will close the dialog and ask for a refund.
You need three things:
An Apple Developer Program membership ($99/year).
A Developer ID Application certificate, downloaded from your developer account and installed in your keychain.
A notarization step in your release pipeline that uploads the signed build to Apple, waits for the green light, and staples the ticket to the app.
The signing and notarization steps are scriptable. A typical release script looks like:
# Sign with hardened runtime<br>codesign --deep --force --options runtime \<br>--sign "Developer ID Application: Your Name (TEAMID)" \<br>MyApp.app
# Submit to Apple's notary service and wait for result<br>xcrun notarytool submit MyApp.zip \<br>--apple-id [email protected] \<br>--team-id TEAMID \<br>--password "@keychain:AC_PASSWORD" \<br>--wait
# Staple the notarization ticket so the app validates offline<br>xcrun stapler staple MyApp.app<br>Run this once locally to confirm it works, then move it into CI so every release is signed and notarized automatically. From a Gatekeeper standpoint, a notarized Developer ID app and a Mac App Store app are equivalent — both open cleanly on a fresh Mac.
Step 2: Take payments with Stripe (or another processor)
With distribution handled, you need a way to take money. The recommended choice is Stripe — you become the legal seller, you own the customer record (email, purchase history, refund history), and fees are roughly 2.9% + $0.30 per transaction instead of the App Store’s 15–30%.
The minimum setup is a Stripe account, a product with at least one price, and either a Payment Link (zero code, paste into your site) or Stripe Checkout (a hosted checkout page you redirect to from a “Buy” button). Both produce the same outcome: when the payment succeeds, Stripe fires a webhook to your server.
That webhook is the source of truth for “a sale happened.” Everything downstream — issuing the license, sending the email, recording the customer — keys off it.
If you’d rather use a merchant of record so someone else handles VAT and sales tax, Paddle and Lemon Squeezy are the established options. They take a larger cut (typically 5–8% of revenue plus per-transaction fees), and they own the customer relationship, but they remove the tax-compliance burden. Gumroad and Polar are lighter alternatives in the same shape. Whichever you pick, the next step is the same — the processor’s webhook tells your licensing layer that a customer paid.
Step 3: Issue and validate license keys
This is the part Apple quietly handles for App Store apps through receipt validation, and the part most developers underestimate when they leave. You need three pieces:
A server-side flow that turns “customer paid” into “here’s a license key in their inbox.”
A client-side check that decides whether the running app is licensed, on trial, expired, or unactivated.
An offline path , so the app opens without a network round-trip every launch.
Keylight handles all three. You point your payment processor’s webhook at Keylight, it issues a key and sends the email, and the macOS SDK validates that key against a signed lease token cached on disk — no internet required after the first activation. Stripe is the default integration, but the webhook contract is generic; Paddle, Lemon Squeezy, Gumroad, and Polar all plug in the same way.
On the Mac side, the SDK surface is small:
import KeylightSDK
let licensing = try! Keylight.manager(<br>sdkKey: "sdk_live_...",<br>tenantId: "acme",<br>productId: "myapp",<br>keyPrefix: "ACME",<br>trustedPublicKeyBase64: "",<br>trialDurationDays: 14,<br>branding: .init(<br>appName: "My App",<br>purchaseURL: URL(string: "https://acme.example.com/buy")!,<br>supportEmail: "[email protected]",<br>tintColor: .blue
await licensing.checkOnLaunch()
switch licensing.state {<br>case .licensed:<br>unlockFeatures()<br>case .trial(let daysLeft):<br>showTrialBanner(daysLeft: daysLeft)<br>case .expired:<br>showRenewalPrompt()<br>case...