How Keys Are Issued and Emailed
The webhook flow#
When Paddle sends transaction.completed with status completed or paid, License Cart:
- Checks idempotency. If the transaction ID was already processed, the event is logged as
skippedand nothing is duplicated. Paddle may deliver the same event more than once. - Finds the customer. The email and name are read from the payload (or fetched from the Paddle API by customer ID if missing).
- Creates a WordPress account for a new email, with the Subscriber role, a random password and the buyer’s name as display name. An existing user with that email is reused. Customers never need the password: they use magic links.
- Creates the License Cart customer record, linked to the Paddle customer ID and the WordPress user.
- Looks up each purchased item by its Paddle price ID. Items that do not match a pricing package are ignored, so a Paddle-only product never creates a stray license.
- Issues a license per matched item with the package’s activation limit, the product, and (for subscriptions) an expiry date of now plus the package’s expiry days. Lifetime packages have no expiry.
- Emails the customer and sends a short plain-text notification to the site’s admin email.
License key format#
Keys are 32 hexadecimal characters in eight groups of four, for example A1B2-C3D4-E5F6-7890-1234-ABCD-EF01-2345, generated from cryptographically secure random bytes and checked for uniqueness.
The purchase email#
Subject: [Site Name] Your License Key — Product Name
The HTML email includes, for each license bought:
- the product name,
- the license key in a copyable block,
- expiry date (or “Lifetime”), maximum sites, and the latest version number if a release exists,
- a secure login link that opens the portal without a password (valid for 30 minutes), and
- a permanent link to the My Licenses portal.
The plain-text alternative contains the same information.
Renewals, cancellations, pauses#
- Recurring subscription payment (
transaction.completedwith originsubscription_recurring): the existing key is kept and its expiry is extended by the package’s expiry days, counted from the current expiry if it is still in the future so early renewals never lose paid time. The customer receives[Site Name] Your license has been renewed — Product Nameand the admin gets a notification. Payment-method changes and plan updates on the same subscription do not mint a second key. subscription.canceled: every license tied to the subscription is set to revoked.subscription.paused: licenses are set to inactive (activations are kept).subscription.resumed: licenses are set back to active.
Expired subscription licenses are marked expired automatically the next time they are checked by a client or the portal.
Was this article helpful?
Tell us what was missing
