Stripe Webhooks for macOS License Keys
A Stripe webhook is the bridge between payment and licensing for a macOS app. Stripe confirms that the customer paid; your licensing system turns that event into a license key the Mac app can activate. For the full direct-sales model, start with how to license a macOS app outside the App Store.
The payment-to-license boundary
Stripe does not issue software license keys. It creates customers, charges cards, manages Checkout, tracks subscriptions, and reports refunds. That is the payment layer.
The licensing layer starts after the payment event. It answers questions Stripe does not own:
- which app did this customer buy?
- which license tier or feature set should they receive?
- how many Macs can they activate?
- is the license still valid after a refund, chargeback, failed renewal, or cancellation?
- what signed token should the app store for offline validation?
That is why a clean Mac app licensing setup connects Stripe to a dedicated licensing system instead of trying to make Stripe itself become the license database.
The webhook that usually creates the key
For a one-time purchase through Stripe Checkout, the event you usually care about is checkout.session.completed.
The practical flow is:
- Your website sends the customer to Stripe Checkout.
- Stripe charges the customer.
- Stripe sends
checkout.session.completedto the licensing system. - The licensing system reads the Checkout Session and line items.
- It maps the Stripe price or product to a Keylight product tier.
- It creates a license key and associates it with the customer email.
- It emails the key or makes it available in a customer portal.
Keylight handles this through its Stripe integration. You keep your Stripe account and customer relationship; Keylight handles key creation and activation state.
Make license creation idempotent
Stripe webhooks can be retried. That is a feature, not a bug: if your endpoint is down or slow, Stripe will try again.
Your licensing system must treat retries carefully. The same Checkout Session should create the same license once. If the webhook is delivered twice, the customer should not receive two independent keys, two activation pools, or two subscriptions in your licensing database.
The simplest rule is to store the Stripe event ID or Checkout Session ID alongside the license. If that Stripe object has already been fulfilled, return the existing license. Keylight does that for you so the Stripe webhook remains safe to retry.
Subscriptions need more than the first webhook
If your Mac app sells subscriptions, checkout.session.completed is only the beginning. Later Stripe events update the license lifecycle:
- successful renewals keep the license active;
- failed payments may start a grace period or mark the subscription past due;
- cancellations change the renewal state;
- refunds and chargebacks revoke or restrict the license.
That lifecycle is where a direct Stripe setup gets more complex. A Mac app needs a local signed lease for offline license validation, but the server still has to reflect Stripe’s billing state when the app refreshes online.
Refunds should update the license automatically
Refunds are not just accounting. If a customer is refunded, the license should be revoked or changed according to your policy.
With Stripe, refund events can update the license server. The app does not need an instant network call on every launch; it can pick up the revocation on the next scheduled online refresh. That is the tradeoff behind refund revocation: customers can still launch offline, and the server catches revoked licenses when connectivity returns.
Where Keylight fits
Keylight is the licensing layer between Stripe and your Mac app. Stripe processes the payment. Keylight receives the webhook, creates the license key, tracks device activations, signs the offline lease, and updates license state when Stripe reports renewals or refunds.
If you are comparing this with other payment providers, read Paddle vs Lemon Squeezy vs Stripe for Mac app licensing. If you are ready to wire the app side, read adding license keys to a Swift macOS app.
Frequently asked
Which Stripe webhook creates a macOS license key?+
For one-time purchases, checkout.session.completed is the usual event. A licensing layer receives it, maps the Stripe product to an app plan, and creates the license key.
Do I need to write my own Stripe webhook handler for license keys?+
Not if you use Keylight. Stripe handles the payment, and Keylight receives the webhook, creates the license, and keeps later refunds or subscription changes in sync.
How should Stripe webhook retries be handled?+
License creation should be idempotent. If Stripe sends the same event twice, the customer should get the same license, not duplicate keys.
Ready to ship?
Create your account and start licensing your apps in under a minute. Free forever tier included.
Start Free