Paddle License Keys: Automate Delivery, Renewals and Refunds
Connect Paddle payments to software license keys. Handle renewals, failed payments, refunds and webhook retries, with a Stripe comparison.
To sell Paddle license keys, connect a confirmed payment to a specific software entitlement. Keep that connection when the customer renews, changes their card or asks for a refund. A checkout success page alone cannot establish whether the license should be issued or extended.
This guide describes PermitCore's vendor Store with Paddle Billing, alongside its existing Stripe option. Each vendor chooses one provider for the entire Store. It does not describe how the vendor pays for their own PermitCore plan. Provider references were checked on 31 October 2026.
Separate payment, license delivery and device activation
Paddle handles its payment, tax and provider document. PermitCore verifies the payment and associates the Store order with a license. Your application still has to validate that key and, when its license model requires it, register a device or obtain a floating seat. Buying a key does not activate every computer automatically.
Decide what each Store product grants before connecting checkout: the underlying product, one-time or recurring price, features and activation limits. A monthly subscription is a billing schedule; a seat is a usage limit. Changing one does not automatically define the other. See device activation and CLI seat policies.
Connect the vendor's account and catalog
Use the step-by-step Paddle setup guide. Start with a separate sandbox account. Save a new connection disabled to obtain its webhook URL, configure the notification destination and signing secret, then enable, save and verify it. The secret API key, public client-side token and destination signing secret have different jobs.
Approve the exact checkout hostname and save the complete default payment link in that same Paddle workspace. Sync the Store catalog, then inspect the connected price for every offered one-time, monthly and annual option. Check currency, amount, interval and tax treatment. A successful API verification badge does not prove domain approval, a completed payment or email delivery.
Click Use Paddle only when ready to change new checkouts for all Store visitors. Browsing the Paddle tab does not activate it. If Stripe remains selected, its saved Stripe connection continues handling new purchases. Existing subscriptions stay bound to their original provider and connection; switching selection is not a subscription migration.
Which events drive the license lifecycle?
Paddle's transaction.completed reference describes the completed transaction, including its payment, subscription and invoice information. PermitCore then retrieves canonical provider data and checks the account, mapped prices, amounts and purchase bindings before applying entitlement changes. A signed event is an authenticated notification, not permission to trust every field as a new purchase.
| Change | Paddle Store input | Stripe Store input |
|---|---|---|
| Initial purchase | transaction.completed | checkout.session.completed; recurring paid periods require invoice.paid |
| Paid renewal | Completed recurring transaction with verified billing period | invoice.paid for the recurring period |
| Failed renewal | subscription.past_due and canonical subscription state | invoice.payment_failed and subscription status updates |
| Subscription change | subscription.updated, cancellation, pause and resume events | customer.subscription.updated and customer.subscription.deleted |
| Refund | adjustment.created and adjustment.updated, with approved refund evidence | charge.refunded |
This table explains the lifecycle; it is not the complete webhook registration checklist. Enable every event shown by the chosen provider's Store settings. The Stripe subscription documentation describes its own events. Keep the destination and credentials in the same test or live environment as the checkout.
A completed zero-value update is not a paid renewal
Updating a saved Paddle card can create a completed zero-value transaction. A prorated downgrade can instead create account credit. PermitCore validates those canonical card-change or credit-only subscription updates and ignores them for paid entitlement: they do not issue keys, extend paid-through dates, send license emails or clear payment debt.
Do not implement a rule that every event containing completed renews access. Equally, do not classify every purchase with no new card charge as invalid: an actual purchase funded by existing credit still needs its normal purchase validation. The transaction's origin, lines, amounts and payment context matter.
Renew the existing key and handle missed payments
A verified paid recurring period extends the original Store license rather than emailing a different key each month. A failed renewal preserves its last paid-through date and starts payment grace. The Store default is 14 days from that date; vendors can configure 0–365 days, and a license's explicit post-expiry grace override takes priority, including zero.
The API's expiresAt is the paid-through date, not the grace deadline. During permitted grace, use isValid, isInGracePeriod and paymentStatus to show an appropriate recovery message. An active subscription snapshot or a successful card update alone does not clear overdue debt. A genuine paid recovery supplies the required payment evidence.
Scheduled cancellation preserves the already-paid period; a final subscription end revokes access. A later event must not revive a manually revoked key. Offline proofs cannot learn about a cancellation or renewal while disconnected: their signed deadlines remain binding. Read failed-payment grace before deciding what your app displays.
Refunds, credits and disputes need different treatment
Paddle can create a refund as pending approval or approve it immediately. Its adjustment documentation explains why both created and updated notifications matter. PermitCore uses approved refund evidence; a pending request is not a completed refund.
For Paddle Store orders, a full approved refund revokes the affected access; a partial refund is recorded without revoking it. Historical payments and provider-issued documents remain visible. A refunded key cannot be revealed in the customer's Purchase History.
A refund does not cancel future subscription billing. Cancel the subscription separately when required, and verify both outcomes. A credit-only adjustment is not automatically a refund. Disputes and chargebacks need an explicit operational policy; do not assume every dispute notification automatically revokes a Store license. Review the provider record and handle the case through authorised account controls.
Make retries safe and failures visible
For your own integration, verify the original request bytes with the destination's secret before parsing and acting. Paddle documents signature and timestamp verification; Stripe's webhook guide covers its signature validation, duplicates and delivery ordering. Keep administrative credentials out of customer apps and webhook URLs.
PermitCore's Paddle receiver stores a durable inbox entry before acknowledging receipt. A worker verifies provider resources and applies order, license and notification-outbox changes transactionally. Event and payment identities prevent a duplicate delivery from minting another key. Acknowledged receipt is not the same as successful processing or a delivered email.
Failed Paddle processing appears in Store → Settings → Paddle → Payment events, with bounded retries and a manual Retry action after the underlying issue is corrected. Compare notification and object IDs with Paddle's delivery logs. Fix revoked credentials, mismatched prices or disabled historical connections before retrying. There is no promise that an event which never reached the receiver will recover by itself: investigate and redeliver it through the provider.
If the order is complete but email is missing, inspect the configured mail delivery and buyer account. Do not charge again or generate a second key as the first troubleshooting step. Payment confirmation, license creation and inbox receipt are separate observations.
Test the whole path before accepting buyers
- Confirm the saved provider and sandbox/test mode, then make a real sandbox purchase through your Store.
- Check processed payment evidence, the completed sandbox order, correct price/tax, provider document and the buyer's license.
- Validate the key for the expected product. Test device activation separately if required by your model.
- Redeliver the same event and confirm there is no extra key or repeated entitlement extension.
- For subscriptions, exercise a paid renewal, failed renewal, paid recovery and final cancellation. Check the original key and actual paid-through dates.
- Test a zero-value card update, a credit-only change and full/partial refunds. Cancel future test billing separately and finish cleanup.
A simulated webhook checks receiver wiring; it does not prove a settled purchase or renewal. Sandbox success does not prove live account approval, tax setup or payouts. Use the provider's current test tools, review orders and delivery logs, and keep historical connections enabled while their subscriptions or refunds remain outstanding.
For the Stripe-specific path, see Stripe checkout and license delivery. For the vendor account walkthrough, open Store provider settings. You do not need to write these payment handlers when using the built-in PermitCore Store.
Build your first licensed product without building a license server.
Create a free PermitCore account, issue a test license, and validate it from your application.