Skip to main content
Plugins Docs About Support Pricing My Account Browse Plugins
Licensing

Bodholdt Licensing

Self-hosted software licensing for WordPress

v10.51.8
PHP 8.0+
WP 6.0+
GPL-licensed
14-day money-back

Get Bodholdt Licensing

Keep 100% of your revenue. No per-sale cut or platform tax from us, though normal payment-processor fees still apply. Choose monthly, annual, or lifetime billing.

Hobby

$49.00 /yr

Paying annually saves 32% against twelve monthly payments.

Self-hosted plugin licensing.

  • 1 product, 1 site
  • License keys + auto-updater
  • Stripe-powered checkout
  • Customer portal + Stripe billing portal
  • SDK generator for your customers
  • Email support from the developer, for as long as your license is active
Buy Hobby →

Studio

$99.00 /yr

Paying annually saves 31% against twelve monthly payments.

Everything in Hobby, plus:

  • Unlimited products (Hobby covers 1)
  • Up to 5 sites
  • Reports & analytics for revenue, MRR, license health, and seat utilization
Buy Studio →
Keep 100%

Foundry

$199.00 /yr

Paying annually saves 17% against twelve monthly payments.

Everything in Studio, plus:

  • Up to 127 sites
  • Keep 100% of every sale, with transparent plan pricing and no per-sale cut; normal payment-processor fees still apply
Buy Foundry →
See full feature comparison →
Feature HobbyStudioFoundry
Sites 15127
Products you can sell 1
License keys + auto-updater IncludedIncludedIncluded
Stripe checkout + customer portal IncludedIncludedIncluded
SDK generator IncludedIncludedIncluded
Reports & analytics Not includedIncludedIncluded
Lifetime license option IncludedIncludedIncluded
Support Email while activeEmail while activeEmail while active

Every paid license includes email support from the developer while the license is active. A one-time (Lifetime) license has no renewal date, so its support does not stop at one. Bug reports, pre-sales and billing questions are always free.

Real screens from Bodholdt Licensing

These are real admin screens, not mockups. Click any one to view it full size.

Issue a license, search, filter, export, revoke it, and manage domain activations. Paid or order-backed licenses are retained; only non-purchase test or manually issued licenses can be permanently deleted.
Issue a license, search, filter, export, revoke it, and manage domain activations. Paid or order-backed licenses are retained; only non-purchase test or manually issued licenses can be permanently deleted.
Your catalogue at a glance: plugin or bundle, the version each product is serving, and a status column that says plainly when something is not ready to sell yet, whether that is a missing purchase plan or a component ZIP that is not in the vault.
Your catalogue at a glance: plugin or bundle, the version each product is serving, and a status column that says plainly when something is not ready to sell yet, whether that is a missing purchase plan or a component ZIP that is not in the vault.
The License tab distinguishes the built-in seven-day evaluation from a paid key, and never renders a saved key back into the page.
The License tab distinguishes the built-in seven-day evaluation from a paid key, and never renders a saved key back into the page.
A guided checklist for Stripe, including the exact webhook events to select, then products, store pages, the client SDK, email delivery and the customer portal.
A guided checklist for Stripe, including the exact webhook events to select, then products, store pages, the client SDK, email delivery and the customer portal.

A complete self-hosted software licensing system for WordPress. Manage license keys, handle activations, process Stripe payments, and deliver updates, all from your own server.

License key generation and management

Stripe checkout for subscriptions, one-time payments, and configurable customer-product trials

SDK generator that produces a drop-in client with an auto-updater and license-status gating

Reports and analytics for MRR/ARR, license health, and seat utilization (Studio and Foundry)

Automatic, license-authenticated updates

Customer portal plus the Stripe billing portal

Product bundles and tier-aware license issuance

License check, activation, and deactivation endpoints, Stripe webhooks, and branded emails

The Sovereign Mint arcade, with ranks, trophies, and a vault that compounds your recurring revenue into XP

  • License key generation and management
  • Stripe checkout for subscriptions, one-time payments, and configurable customer-product trials
  • SDK generator that produces a drop-in client with an auto-updater and license-status gating
  • Reports and analytics for MRR/ARR, license health, and seat utilization (Studio and Foundry)
  • Automatic, license-authenticated updates
  • Customer portal plus the Stripe billing portal
  • Product bundles and tier-aware license issuance
  • License check, activation, and deactivation endpoints, Stripe webhooks, and branded emails
  • The Sovereign Mint arcade, with ranks, trophies, and a vault that compounds your recurring revenue into XP
Version
10.51.8
PHP Required
8.0+
WordPress
6.0+
Setup
About an hour, once
License
Commercial GPL
v10.51.8 · Sep 5, 2026
  • Wording only. When a license has ended, the page that lists it now says that if you need a copy of what you had, you should write in and we will sort it out. It previously pointed you at buying again, which is not an answer to the question somebody in that position is actually asking. Nothing about what a license does or does not allow has changed: an ended license still does not download or update, and the plugins it licensed keep running on your sites, because they are GPL and self-hosted and the copy you installed is yours.
v10.51.7 · Sep 5, 2026
  • Your purchase email now says which tier you bought and how many sites the key covers. It named only the product, so a Studio or Foundry buyer had to open the portal to find out what they actually had.
  • The billing button on the licenses page no longer does nothing when the page has been open a while. An expired page token made the button silently reload the page with your email wiped and no message at all, which reads exactly like a broken site. It now says the request expired and asks you to try again.
  • The "not included" dash in the plan comparison table was too faint to meet the contrast standard. It is now readable, and still visibly dimmer than the text around it.
  • The buying page said every plugin ships with a money-back guarantee and email support. Both are true of the paid plugins; the free-only ones have nothing to refund and no license to carry support. GPL licensing, which really is true of all of them, is now its own sentence.
  • Translators following the source references in the shipped catalog no longer land on files that are not in the download.
v10.51.6 · Sep 5, 2026
  • A one-time purchase no longer receives an email explaining how to cancel a subscription. Every purchase email ended with a Manage Subscription heading and button, whichever way you had paid, so a customer who bought a lifetime license was given cancellation instructions for something they never had. The destination was always right, because that page is where both kinds of customer manage their licenses; only the label was wrong. It now says what the order actually was, worked out from the licenses in the order rather than restated.
  • The billing-link form can no longer be used to send repeated emails to somebody else's address. It is a public form that takes any email, and it was capped only by requests per minute per visitor, so one visitor could aim a long run of messages at an address they chose. It is now also capped per recipient, in the same shape the verification-code form has used since 10.18. Both caps answer exactly as a successful request does, so nothing about them reveals whether an address has an account.
v10.51.5 · Sep 5, 2026
  • The key-lookup page no longer says a code was sent when it sent nothing. If you asked for a code less than a minute ago, or you have reached the daily limit, it now says exactly that instead of "New code sent! Check your inbox." This mattered most to the person it was worst for: if your license email had not arrived, the order page sends you here to look your keys up, and clicking Resend a few times could leave you told five times that a code was on its way when none was. The Resend button also counts down now rather than letting you ask again into a wall.
  • A license that has ended is shown to you instead of being hidden. Before, an expired or cancelled license vanished from the lookup entirely and the page said it could not find any licenses for your email and suggested you check the spelling, which is the wrong thing to tell someone about a purchase they really made. Ended licenses are now listed with the date they ended, marked clearly as no longer active, and with no download button, because they do not download or update. What you can still do is unchanged.
  • The Bodholdt Tickets plans now say that licensing-aware customer context needs Bodholdt Licensing installed on the same site. It always did, and the plugin's own readme said so, but the buying page did not.
v10.51.4 · Sep 5, 2026
  • Nothing in your install changes in this release either. Like 10.51.3 it touches only the file that renders the Bodholdt Labs storefront, which is not part of the plugin you receive.
  • What changed there: the Bodholdt Atelier comparison box told a free-edition reader that email support was not included, and then two lines below told them that bug reports, pre-sales and billing questions are always free. Both were true and together they were confusing. The note now says the whole of it, including that free-edition questions get answered when we can. The row is unchanged, because a license really is what makes support a commitment rather than a courtesy.
v10.51.3 · Sep 5, 2026
  • Nothing in your install changes in this release. The only file it touches is the one that renders the Bodholdt Labs storefront, which is not part of the plugin you receive, so this entry is here for the record rather than because there is anything for you to do.
  • What changed there: our own top tier no longer claims priority email support, because nothing anywhere ever delivered it. There was no mailbox rule, no queue, no service level and no routing that treated one customer's email differently from another's, so the claim described an intention rather than a behaviour. It is deleted rather than softened, since a gentler version of the same sentence would still say that customers on the tiers below wait longer, and that would have been a new thing to be wrong about. Every paid tier gets email support from the developer while the license is active, which is what our support page has always said and what actually happens.
v10.51.2 · Sep 4, 2026
  • A store no longer locks itself when it cannot reach us. If thirty days passed without a successful licence check, this plugin used to treat that as an expired licence and switch off checkout, the pricing page and new licence creation, even though nothing was wrong with the licence and the only thing that had failed was reaching bodholdtlabs.com. Your own outage is not your customers' problem, and it is not ours to make yours. The store now keeps working, and the admin notice asking you to check that your server can reach us stays on screen while it does. A licence we have actually declined still stops new licence creation, exactly as before.
  • Support credits are retired. Every paid licence now includes email support from the developer for as long as the licence is active, and a one-time licence has no renewal date to stop it. Lifetime purchases no longer grant a credit balance, the pricing pages no longer describe one, and nothing is taken from anyone: no credit was ever issued. If you run your own support desk on Bodholdt Tickets, its credit feature is untouched and still yours to switch on.
v10.51.1 · Sep 2, 2026
  • The two update check routes no longer invent a version. A product that is in your catalog but has no entry on the Product Versions screen used to be answered with version 1.0.0, tested up to 6.9, requires PHP 8.0 and an empty changelog, none of which you had set. Both routes now answer it the way they answer a product they have never heard of: the query string route with result error and Product not found, the REST route with a 404. Nothing changes for any product that has a version set, and nothing changes for the free self-served products, which already answered this way.
  • No installed copy could have been harmed by the old answer, because 1.0.0 never compares higher than a version that is already installed. The route was simply stating a version that did not exist, and this release makes it say so instead.
v10.51.0 · Sep 2, 2026
  • Reports, Downloads now records two versions for every download instead of one. The first is the version your Product Versions screen advertised at the moment of the download, which is what the report has always shown. The second is the version read from the plugin header inside the ZIP that was actually sent. When the two differ the row says so, a short notice sits above the table with the count, and the CSV export gains a Served version column and a Match column so the same comparison survives a spreadsheet.
  • Why both: a version pointer and a file on disk can drift apart, and until now the report could only ever repeat the pointer. Recording what was really sent makes that drift visible in the one place you already look.
  • Where the second version comes from. Bodholdt Licensing does not open archives itself. It asks for a reader through the new cls_downloads_served_version_reader filter, which takes a callable that receives the absolute path of the file about to be streamed and returns its version, or an empty string. If nothing supplies a reader the column stays empty and the report shows "not read", never a match it did not establish. The reading happens before the first byte is sent and can never cost anyone the download: anything the reader prints is discarded and any error it raises is swallowed.
  • This adds one column, served_version, to the downloads table. It arrives the way every schema change here arrives, through the self-heal that runs on the first page load after an update, so there is no activation step. The table stays anonymous: no address, no browser, no key. A file's version is a fact about the file.
  • On the Bodholdt Labs store itself, a host-only change that is not part of the plugin you run: the download button on the two free backup plugin pages keeps recording a real version after the retired paid entries are stood down, by reading the free edition's own version entry instead.
v10.50.1 · Sep 1, 2026
  • A storefront-only release. Nothing in the plugin you run changed. The files that changed are the Bodholdt Labs store pages, which are host-only and have never been part of the distributed plugin, so this build is byte-for-byte 10.50.0 apart from the version strings and this note. There is no reason to hurry the update.
  • Recorded here because the store's changelog and yours are the same file. Bodholdt Backup Pro, the paid companion for the two backup plugins, is on the store's pricing page now instead of only being reachable by a direct link: it gets its own section, its own card and its real prices, and the two free backup sections link to it rather than only naming it.
  • The wording is careful for the same reason it was careful last release. The free backup editions already email you after every backup attempt, success or failure, and both new paragraphs say so before they say anything about the companion, so nobody can read this as the moment they start being notified. What is sold is the delivery channel and the digest, never "alerts" on their own.
  • The companion's own section leads with the fact that it is an add-on and takes no backups of its own, because one of the two backup plugins has to be running for it to have anything to report on.
  • No price changed. The backup plugins are still free with no paid plan, and their checkout is still closed with the same explanation.
v10.50.0 · Sep 1, 2026
  • The two backup plugins are free now, with no paid plan, and the store says so everywhere at once.
  • Bodholdt Backup for Google Drive and Bodholdt Backup for OneDrive had a $29/yr Complete plan. It is retired. Everything it included is in the free edition, including the dashboard updates that were the last thing it alone could do, and the Slack and Discord delivery it also carried now lives in Bodholdt Backup Pro, a separate companion that covers both clouds on one license and adds a scheduled backup-health digest. So the buy links, the cart builder and the public products feed all stop offering the two backup plugins, and the free card is the only card left on their pricing block.
  • Nothing was deleted to do it. Both products keep their catalog entries, their Stripe objects and their update pointers exactly as they were, because existing licenses activate and update through them. If you hold one, nothing about it changed. Only the checkout closed, and a stale buy link now explains that the plugin is free rather than failing with an unhelpful error.
  • Two things this release is careful about, because they have been got wrong before. The free backup builds have always emailed you after every backup attempt, success or failure, so no copy anywhere now implies a free user hears nothing when a backup fails; the companion is described by what it actually adds, which is the chat channel and the digest. And the pricing block no longer falls back to the backup family's copy for a product it does not recognize. It used to, which is how a companion plugin that takes no backups once rendered a card promising full and incremental backups. An unknown product now renders nothing.
  • The free-download line under each download button names the product when the product has one edition, and keeps naming the edition when it does not.
v10.49.1 · Sep 1, 2026
  • Two fixes: a way to keep a product out of the store listing without taking it off sale, and an update check that finally reports the WordPress versions you configured.
  • Products can now be marked "Unlisted". An unlisted product is left out of the cart builder and the public products feed, so it is not advertised, but nothing else about it changes. Anyone with a direct buy link can still buy it, licenses still activate, downloads still work, and updates still arrive. There is a checkbox for it in the product editor, and the products list shows an Unlisted badge so it is not forgotten.
  • The update check now answers with the WordPress compatibility fields it was given. It was renaming "tested_wp" and "requires_wp" to "tested" and "requires" in the response, while every client reads the original names. The result was that installed plugins showed an empty "Tested up to" and a fixed "Requires WordPress 6.0" no matter what was published for them. Both spellings are sent now, so existing installs are fixed without anyone needing to update anything first.
v10.49.0 · Aug 31, 2026
  • The store now says what a paid backup plan is really for, and the checkout page looks like ours.
  • The paid backup plan's bullet list led with automatic updates. Alerts and support are the substance of the plan, so they come first now, and the updates line says plainly that updates install from your dashboard while your license is active.
  • The free download blurb is scoped to the edition it describes. It used to promise "no license key" in the name of the whole product, on the same page that sells a keyed edition of that product.
  • The Atelier pages no longer sell automatic updates as something a license adds. The free Lite edition ships a working updater with no key to enter, so that line was wrong. A license adds email support and a site allowance of up to 127 activations.
  • The "Confirm your purchase" page now carries the Bodholdt Labs mark, wordmark, and site colors, so it reads as part of bodholdtlabs.com instead of a plain unbranded page. It still loads nothing from anywhere: no external requests, no third-party assets, and the checkout flow itself is unchanged.
v10.48.5 · Aug 30, 2026
  • Rate limits on the public endpoints now allow the number they say.
  • WordPress asks a REST route for permission twice on every request, once to serve it and once more to work out which methods that route allows. Both asks were counted, so a limit set to thirty a minute was letting through fifteen. The answer is now worked out once per request and reused, so the configured number is the number enforced. Nothing about the limits themselves changed.
v10.48.4 · Aug 30, 2026
  • The page you land on after paying no longer says your purchase is unavailable.
  • Stripe sends you back to the site the moment your payment goes through, but the confirmation that unlocks your keys arrives separately, a second or two later. The page could not tell that short wait apart from a link that had genuinely expired, so it showed the same discouraging message for both, and it never updated.
  • It now says your order is being confirmed, checks again on its own for up to thirty seconds, and then, if something really is stuck, tells you plainly what to do and gives you a support address. A link that has actually expired reads the same as before.
Show the full release history (63 older releases)
v10.48.3 · Aug 30, 2026
  • The Atelier section of the store finishes catching up with the change to one product.
  • Its product page was still drawing three plan cards. Two of them had no name, no description and an empty button, because the plans they pointed at were retired last week. Those two cards are gone and one remains.
  • The site allowance is now stated as what it actually is. Several places said a license covers unlimited sites; a license record holds up to 127 activations, so that is what they say now.
  • The question "what is the difference between Solo, Pro and Agency" has been removed from the Atelier page. Those plans no longer exist, and the answer quoted prices for them.
  • The plugin catalog and the home page now lead with the free edition for the four plugins that have one, with the license price underneath, instead of showing only a price.
v10.48.2 · Aug 30, 2026
  • A failed download could return a database error page instead of the plugin ZIP.
  • The download recorder claimed in its own documentation that it could never break a download, but it only checked that its table existed. If the database connection dropped, WordPress retried for about five seconds and then rendered its database error page, and because the recorder runs before any of the file is sent, that page arrived in place of the ZIP.
  • The file is read from the disk and never needed the database. So when the database cannot be reached the download now proceeds and only the download statistic is lost, which is the right way round.
v10.48.1 · Aug 30, 2026
  • Three product sections on the store page were showing each other's copy.
  • The paragraph under Bodholdt Tickets described Bodholdt Licensing, the one under Bodholdt Atelier described Bodholdt Tickets ("up to 3 agents, unlimited tickets, and Claude-BYOK AI", none of which are Atelier concepts), and Atelier's own paragraph had ended up at the foot of the licence-expiry FAQ, which is not a product section at all. Each section now carries its own description.
  • Atelier's description also stops implying its free edition is a reduced one.
v10.48.0 · Aug 29, 2026
  • Bodholdt Atelier is now one product on the storefront instead of four cards.
  • The ladder was removed because it was inverted rather than merely complicated. The free edition of Atelier ships an all-open licensing stub, while a paid base-tier licence locked the Foundry, the Marketplace and the Lightroom publish API. Paying made the product worse than not paying. The Agency tier, meanwhile, added no feature over Pro at all: its only differences were a seat count and priority support.
  • So the pricing page now shows Free Lite beside a single Atelier licence, and every feature row in the comparison table is a tick in both columns. A licence buys automatic updates in your dashboard, support, and an unlimited site allowance. It does not buy a feature.
  • A tier that is no longer sold now says so. The retired-tier check runs before the valid-tier check, so following an old "Buy Pro" link tells you the tier was retired rather than that it was invalid, whether or not it still exists in the product configuration.
  • Also in this release, and unrelated: the shared arcade toast script now sanitises the icon markup it is handed and coerces the points value before writing either into the page. That hardening was written on 28 August and had not reached the site.
v10.47.0 · Aug 27, 2026
  • When a license is issued, the plan and the number of sites it allows now always come from the same place. Before this they were set separately, so a license could be labeled with one plan while allowing the site count from another. Every route that creates a license goes through one check now, including bundle purchases that apply a tier to each product they grant. If a request arrives with a count that does not match the plan, the plan wins and one line goes into the activity log.
v10.46.1 · Aug 27, 2026
  • A signed download link is now tied to the product it was issued for, so a link for one product cannot be edited into a link for another. The link settings also explain, where you set them, why the single use mode is not offered yet.
v10.45.0 · Aug 27, 2026
  • Purchase emails now carry a real download link for each product bought, good for 24 hours, instead of one link to a page repeated for every item. The link carries no license key and is tied to one product and one license, so a copied link is not an anonymous pass. When it expires, the customer portal still has everything.
v10.44.1 · Aug 27, 2026
  • The dashboard File Storage line now tells the truth about a protected uploads folder. If the protection test passed it reads as done, rather than as something you still need to go and fix. A folder that is inside the web root by accident still reads as a warning.
v10.44.0 · Aug 27, 2026
  • Paid files can now live in a protected folder inside WordPress uploads, so a store on shared hosting can sell without a folder above the web root. The plugin creates the folder with a long random name, writes deny rules for Apache and IIS, and then tests the protection from the outside before it will serve anything from there. If it cannot prove protection it says so plainly and shows you the rule to paste. Downloads now send Cache-Control no-store, so a CDN cannot keep a copy of a paid archive at its edge.
v10.43.23 · Aug 26, 2026
  • Groundwork for the protected uploads folder and the check that proves it from the outside.
v10.43.22 · Aug 26, 2026
  • Plainer punctuation across the operator screens.
v10.43.21 · Aug 26, 2026
  • Accessibility pass across the pricing page and the customer portal.
v10.43.20 · Aug 25, 2026
  • Three screens stopped claiming more than they had actually checked.
v10.43.19 · Aug 25, 2026
  • The account credit shown to a customer is now worked out from their real balance instead of repeated from a fixed line of copy.
v10.43.18 · Aug 25, 2026
  • The setup wizard no longer reports a step as complete unless it actually checked it.
v10.43.17 · Aug 25, 2026
  • Fixes a setting that was keeping every customer storefront out of search engines.
v10.43.16 · Aug 25, 2026
  • Plainer punctuation in the copy your customers read.
v10.43.15 · Aug 25, 2026
  • The free support door stops advertising the paid one. Update checks are cached as well, so a busy store makes fewer round trips.
v10.43.14 · Aug 25, 2026
  • An error on the payment path is now handled inside checkout, instead of leaving the customer to interpret a separate failure.
v10.43.13 · Aug 25, 2026
  • The buy page shows the price first.
v10.43.12 · Aug 24, 2026
  • The arcade is fully translatable now, and its toasts can be dismissed. Several labels the arcade shows (the dismiss button, the "Nice" message on a plain points toast, and the level badge) stayed in English no matter what language your site runs in, because the shared arcade code never passed them through for translation. They now translate like everything else, the level number is formatted for your locale, and every celebration has a close button. Toasts also pause while you hover or focus them, and skip their timer entirely if you have asked your system to reduce motion.
  • A site that cannot create the arcade tables now keeps trying. On a host where the database user is not allowed to create tables, the plugin recorded the arcade as installed anyway and never tried again, so the arcade stayed silently broken forever. It now confirms the tables really exist before recording success, and retries later if they do not.
v10.43.11 · Aug 24, 2026
  • The Fun Pass box now matches the arcade. Since 10.43.10 the arcade has been off on a fresh install, but the Fun Pass checkbox under Settings, Arcade still drew itself as switched on, and saving that panel turned the arcade on for real. The box now shows the truth. If you had turned the arcade on yourself, it stays on.
v10.43.10 · Aug 24, 2026
  • The arcade (XP, ranks, HUD, confetti) is now off by default. Turn it on any time under the plugin's Arcade settings. Nothing else changes.
v10.43.9 · Aug 21, 2026
  • Small copy corrections on the pricing block. A few lines on the storefront pricing block did not match what the product pages said. They now agree.
v10.43.8 · Aug 21, 2026
  • The translation catalog now carries the corrected spellings. The spelling and copy sweep from 10.43.7 reached the strings translators work from, so a translated store no longer inherits the old wording.
v10.43.7 · Aug 21, 2026
  • American spellings throughout the customer-facing copy, and one price that disagreed with itself. The checkout confirmation screen printed the raw catalog value, so a card reading "$99.00" was followed one click later by "$99" for the same product. Both now run through the same formatter. Identifiers, function names, and code samples were deliberately left alone, so nothing you have built against the plugin changes.
v10.43.6 · Aug 21, 2026
  • Free downloads are one click again. Four of the five free builds sat behind an email gate: enter an address, wait for a six-digit code, enter the code, then get the link by mail. It was never access control, since the builds are GPL and the download route is public by design. The gate is gone, and the unused claim endpoint and mail helper went with it.
v10.43.5 · Aug 21, 2026
  • Accessibility pass on the pricing block and the customer portal. Three gradient colors failed contrast against the page behind them, the worst at about 3.1 to 1. All three were lightened on the same hue to at least 5.5 to 1, which improves them both as text and as backgrounds under dark text.
  • The comparison table is usable on a phone again. At 375px the first column was wider than its own container, so every tier column started off-screen with nothing to show there was more to see.
v10.43.4 · Aug 21, 2026
  • The billing email no longer sends a wall of identical buttons. Checkout creates a new Stripe customer record whenever a buyer does not reuse an existing session, so one person accumulates several, and the email emitted one button per record labeled only "Billing account 2 (canceled)". Each link is now named after the plan it manages, and while any subscription is still live the dormant records are left out instead of listed.
v10.43.3 · Aug 21, 2026
  • A verified email with no licenses now has a way forward. Someone who verified their address and owned nothing was told we could not find any licenses, and was then shown a prompt to buy a support credit, on a screen with no link to the store anywhere. The empty state now points at the store instead of asking someone who owns nothing to buy support for nothing.
v10.43.2 · Aug 20, 2026
  • The Getting Started Guide now lists every webhook event the plugin actually requires. It said seven; the endpoint check has required nine since 10.39.0 and fails closed until all nine are enabled, so anyone who followed the guide left paid checkout permanently blocked on their own store. The guide now renders the list and the count from the same source the check enforces, so the two cannot drift apart again.
  • Lifetime support credit grants are now bounded. The grant scales with a licence's seat allowance, and its top branch scaled linearly with no upper limit, so a 127-seat lifetime tier issued 762 non-expiring credits against your own support capacity. The ladder is unchanged (15 / 50 / 150) and is now capped at 150. Set CLS_LIFETIME_CREDITS_MAX in wp-config.php, or filter cls_lifetime_credits_ceiling, to choose your own ceiling.
  • The purchase email says the download link is valid for 24 hours, which it always was, and the trial email now carries a link back to the customer portal. Previously a trial customer's email contained no route back.
  • Housekeeping: the readme's stable tag matched an older release than the plugin header, and the translation template still referenced a file removed from the build.
v10.43.1 · Aug 19, 2026
  • The packaged archive no longer carries code for retired products. class-cls-vault.php, class-cls-watch.php, and the Google Drive written-consent gate were still in the download at about 144 KB. Nothing referenced them and nothing loaded them, so no behavior changes, but they should not have been shipping.
  • Changelog corrections. The 10.41.1 entry described a Google Drive consent gate and holds on Vault, Watch, and the Backup Bundle as if they were in force. They are not: the gate was removed in Google Drive 6.47.1 after the clause behind it turned out to be misquoted, and the rest are retired. That entry now says so, and the changelog states plainly which products are retired.
  • Note on older entries: anything below 10.42.0 that mentions Bodholdt Vault, Bodholdt Watch, or the Backup Bundle is history, not a current feature. All three are retired. They are not sold, they are not loaded, and they are not part of any current plan. They stay in this list only because it is a record of what shipped when.
v10.43.0 · Aug 19, 2026
  • The Payments screen now lists the webhook events the plugin actually requires. It showed seven events and said "all seven required events" while the readiness check fails closed on nine, so an operator who followed this screen subscribed to seven and blocked paid checkout on their own store. The list, the count and the wording are now built from the same source the readiness check reads, so the two cannot drift apart again. The two that were missing are checkout.session.async_payment_succeeded and checkout.session.async_payment_failed, which cover delayed settlement methods.
  • Your pricing page is no longer hidden from search engines. The plugin was sending noindex, nofollow, noarchive on whichever page is configured as your shop. That page is a public price list with no customer data on it, and hiding it kept your most important commercial page out of search results entirely. Your order-confirmation and account pages are still protected, because those can show license keys and billing state.
v10.42.4 · Aug 17, 2026
  • Accessibility fix. Two admin tables, the download report and the reviews list, were drawing their alternating rows with a light grey background inherited from WordPress while the plugin uses light text, leaving those rows at roughly 1.5 to 1 contrast against a 4.5 to 1 standard. They now use the same dark stripe as every other table and read at roughly 9.8 to 1. No text colors changed and no data changed.
v10.42.3 · Aug 16, 2026
  • Corrected the required Stripe webhook event count in the setup instructions. The documentation said seven where the plugin requires nine and fails closed until all nine are present.
  • The free-download email no longer opens by thanking the reader for a purchase they did not make.
  • Ships includes/product-retirement-policy.php, which the main plugin file requires and which the previous packaged build omitted.
v10.41.1 · Aug 9, 2026
  • Historical entry, superseded. This release added a written-consent gate that blocked Google Drive checkout, license issuance and activation, and it recorded holds on the Backup Bundle, the legacy Cloudflare R2 Vault prototype, and Bodholdt Watch. The clause behind the Google Drive hold was later found to have been misquoted. The gate was removed in Google Drive 6.47.1, Google Drive is sold and activated normally, and the Vault and Watch code paths are retired and are never loaded. Nothing described in this entry is in force.
v10.41.0 · Aug 8, 2026
  • Internal, unreleased groundwork added quota-reclaim behavior for the disabled legacy Vault prototype. It is not a customer-facing storage service.
v10.40.0 · Aug 8, 2026
  • Internal, unreleased groundwork added an optional legacy R2 storage prototype. It is disabled for customer and production use; historical provider options do not activate it.
v10.39.3 · Aug 8, 2026
  • Maintenance release. The Backup Bundle description now mentions the included Bodholdt Watch backup assurance, and internal build tooling now handles multisite correctly.
v10.39.2 · Aug 8, 2026
  • Removed decorative emoji across the plugin for a cleaner interface; the checkout accent color now meets contrast standards on dark and light themes.
v10.39.1 · Aug 8, 2026
  • Checkout success page license card now adapts to the store theme for readability; removed a decorative emoji; renamed an admin dashboard estimate for accuracy.
v10.39.0 · Aug 7, 2026
  • New: optional Stripe Managed Payments support. When the operator enables the cls_managed_payments_enabled option, new checkout sessions ask Stripe to act as merchant of record through its Link service, so Stripe calculates, collects, and remits applicable taxes and selects the available payment methods. The feature is fully inactive unless enabled, and existing subscriptions always keep their current billing.
  • New: a cls_managed_payments_excluded_products option keeps specific products, such as human support services, on the ordinary card rail. A checkout containing an excluded product uses the ordinary rail for the whole session.
  • The webhook listener now understands the async payment outcome events that delayed settlement methods produce, fulfilling an order when the funds arrive and acknowledging a failed payment without changing any state. Both events are part of the required webhook endpoint configuration.
  • When Managed Payments is enabled, the canonical Stripe Price check also requires a tax code on every non-excluded product, and a tools script reports and backfills tax codes for existing products.
  • The lifetime revenue counter now reads the tax exclusive subtotal instead of the session total, so buyer taxes that Stripe remits are never counted as revenue. The two figures are identical on the ordinary card rail.
  • Stripe objects removed by a customer data deletion request now produce a clear explanation instead of a generic retrieval error.
v10.38.1 · Aug 7, 2026
  • The pricing page now describes the included Bodholdt Watch backup assurance on the paid Backup tiers and the Backup Bundle.
v10.38.0 · Aug 7, 2026
  • New: optional Bodholdt Watch integration. When the operator configures the three cls_watch_* options, successful activations and license checks return a signed site token, and license lifecycle changes (activation, renewal, cancellation, refund, revocation, expiry) sync to the Watch backup assurance service through a durable retry outbox with a weekly reconciliation snapshot.
  • The integration is fully inert until configured: with the options unset there are no new response fields, no new scheduled tasks, and no outbound requests. Self-hosted stores are unaffected.
  • Event delivery never runs inside a license lock or on a customer facing request path, so checkout, activation, and Stripe webhooks keep their existing timing even if the Watch service is unreachable.
  • Reliability: if event delivery keeps failing for more than 24 hours, the weekly task emails the site administrator with the count and the most recent error.
v10.37.6 · Jul 23, 2026
  • Pricing accuracy: removed the "Streaming restore (FK-safe, BLOB-safe)" line from the paid Backup tier. The free build's full restore already uses that same streaming, FK-safe, BLOB-safe engine, so it was never a paid upgrade. The genuine upgrade is selective restore, choosing what to restore, which the tier already lists.
  • Documentation: backfilled the release history below (10.24 through 10.37) so the changelog reflects the full recent record.
v10.37.5 · Jul 23, 2026
  • Pricing accuracy: the Backup Agency tier now reads "Up to 127 sites" (and 127 in the comparison table and the agency FAQ) instead of "Unlimited", matching the enforced activation limit.
  • Copy polish: removed em dashes used as sentence punctuation in the Backup Bundle heading and the Licensing pitches, and demoted the pricing section heading to <h2> so each page has a single <h1>.
v10.37.4 · Jul 23, 2026
  • Fixed: higher pricing tiers (Pro, Agency, Studio, Foundry) could not complete checkout. The payment-boundary price check compared the tier's Stripe price against the wrong product and returned a price mismatch, bouncing buyers back to the pricing page. Non-default tiers now check out correctly.
  • Fixed: the "Manage Billing & Subscriptions" button on the customer subscription-management page did nothing. It now submits and emails the billing-portal access link as intended.
v10.37.3 · Jul 20, 2026
  • Stripe webhooks now acknowledge checkout sessions created by other integrations on the same Stripe account, so unrelated events cannot disable the webhook endpoint.
  • License activation is serialized regardless of key letter casing, so the per-license site limit cannot be bypassed by concurrent requests.
  • A licensed store re-verifies from any page load when the scheduled check has not run, instead of self-locking after 30 days on hosts without wp-cron.
  • Reports keep showing the last known figures when Stripe is briefly unreachable, instead of a fresh 0.
  • Fixed two Settings notices that reported success when a store page slug or vault path was actually rejected.
v10.37.2 · Jul 17, 2026
  • Enforces Hobby, Studio, and Foundry activation and product entitlements against the canonical commercial-license ledger, including Multisite.
  • Verifies replacement keys before saving, preserves a working state during transient failures, and releases activations on clear or uninstall.
  • Hardens generated clients and the built-in updater so license keys stay out of URLs and are sent only to an exact matching HTTPS origin and product.
  • Validates carts, canonical Stripe Prices, currencies, recurrence, products, tiers, bundles, and trial rules on the server before Checkout.
  • Makes checkout fulfillment, subscription state, refunds, disputes, and email retry ordered, durable, transactional, and idempotent.
  • Requires all nine documented Stripe events and proves webhook readiness before paid checkout.
  • Makes the private product vault fail closed, validates exact product references on downloads, applies download throttling, and redacts operational logs.
  • Hardens customer OTP, portal, review, REST, AJAX, admin, settings, product, license, and GDPR paths against replay, enumeration, injection, privilege, and data-integrity failures.
  • Corrects expiry-date boundaries, domain-seat locking, manual Stripe sync, review eligibility, currency handling, plan limits, and multi-customer billing portal access.
  • Removes customer email addresses from portal URLs and persistent browser cookies and applies private-cache/referrer protections to sensitive pages.
  • Makes settings migration exclude credentials and environment-specific storage paths and makes uninstall/network cleanup deliberate and consistent.
  • Updates first-run guidance, translation catalog, compatibility declarations, public documentation, and sanitized release screenshots.
v10.37.1
  • Shared admin engine reconciliation across the Bodholdt product line.
v10.36.0
  • Admin dashboard: optional recurring-revenue "Compounding Vault" view added to the built-in gamification, with a Settings > Arcade switch to turn the whole layer (and its motion and sound) off.
v10.35.0
  • Introduced an optional, fully dismissible admin gamification layer that respects reduced-motion preferences.
v10.34.0
  • Admin redesign across the board: refreshed Dashboard, Activity Log, and Manage Licenses (status chips, inline expiry editing, per-row menus, and a bulk-action bar), cleaner Settings sub-tabs, a clearer "Connect a Plugin" screen, and a split list/editor for Products with safer per-product saving.
v10.33.0
  • Added download tracking and a Reports > Downloads section.
v10.32.0
  • New Sender Identity settings with a live email preview.
v10.31.0
  • Portable customer-reviews display you can place on any page, plus a support line in review-request emails.
v10.30.0
  • Automatic post-purchase review-request email.
v10.29.0
  • Verified customer reviews, so only real, purchase-linked customers can leave one.
v10.28.0
  • Pricing-page refinements and Free-card alignment on the buy-plugins page.
v10.27.0
  • Aligned the Atelier pricing and pitch copy.
v10.26.0
  • Wired the Atelier product family into the pricing page and comparison matrix.
v10.25.0
  • Entitlement gating for the free "Lite" builds.
v10.24.0
  • Self-serve free tier: the free build became a direct, no-key download (with abuse caps and Cloudflare-aware IP trust), and the marketing copy was realigned to the free-and-paid model.
After purchase, you'll receive a download link and license key by email. In your WordPress admin, go to Plugins → Add New → Upload Plugin, choose the ZIP you downloaded, click Install, then Activate. The plugin will prompt you for your license key on its settings page. Paste it in and you're live.
Each WordPress installation domain that activates the key counts as one site, including staging and development domains. Clear the key on an old site to release its activation before moving it.
Yes. Contact support before changing plans so we can confirm the price, effective date, and license limits for your order. Your current entitlement remains in place until the change is confirmed.
Yes. Contact support before renewal so we can confirm the effective date and the site limit that will apply. We do not silently deactivate existing sites.
Lifetime means the supported lifetime of the product, not the customer's lifetime. For a normal discontinuation, we aim to give 12 months' notice and a license for the closest equivalent successor. A binding legal, provider-policy, security, or privacy issue may require an earlier stop and a bounded recovery path instead. The current Terms of Service govern the details.
Yes. Open the Stripe billing portal from your account dashboard and cancel there. You keep access until the end of the billing period.
14 days, no questions asked, full refund. Open a ticket on our Support page (bodholdtlabs.com/support) using the email you bought with.
Two reasons: Stripe's per-transaction fees compound when you charge 12 times instead of once, and monthly subs have higher churn risk for us. Annual or lifetime is the better deal if you know you're sticking around.
Hobby licenses 1 product on 1 site. Studio unlocks unlimited products, 5 sites, and the full reporting dashboard for revenue, MRR, license health, and seat utilization. Foundry raises the activation limit to 127 sites. Current monthly, annual, and lifetime prices are shown in the pricing cards above. All three include license keys, the auto-updater, the customer and Stripe billing portals, and the SDK generator.
There is no separate free edition. The commercial plugin includes a built-in 7-day evaluation with every feature unlocked, no license key, and no card required. That gives you time to wire it into your store and try the checkout, licensing, and SDK flow before activating a paid key. Every plan is also backed by a 14-day money-back guarantee.