API Access & Documentation

Implementing a Robust Software Distribution and Licensing System

By the Domain India teamPublished 9 min read
Knowledge base article
Contents (8 sections)

Writing a PHP application is half the job if you plan to sell it. You also need a way to deliver it to buyers, let them update it, and make sure each copy is used under the licence they paid for. This guide walks through a practical design for PHP software distribution and licensing in 2026: the licence model, signed licence keys, activation, a licence server, and delivering updates.

Key takeaways

Issue each buyer a licence key that your server signs with a private key, and ship only the public key inside your application, so copies can check a licence offline and nobody can forge one. Activate each installation against your licence server once, re-check it occasionally with a grace period, and deliver downloads and updates through short-lived links tied to a valid licence. Protect the licence check itself with an encoder, and never let a failed check destroy customer data.

1. The parts of the system

A working setup has five parts:

Licence model
What the buyer is allowed to do: how many sites, for how long, with which updates.
Licence keys
A key per purchase that the application can verify.
Activation
Tying a key to a specific installation, usually a domain.
Licence server
Your API and database that issue, activate, check and revoke licences.
Distribution
Download links, versioned releases and an update channel.

Build them in that order. The model decides what the keys must contain, and the keys decide what the server has to check.

2. Choose a licence model

ModelHow it worksSuits
Perpetual with yearly updatesPay once, use forever, pay again for updates and support after a yearScripts and plugins sold to small businesses
SubscriptionPays monthly or yearly; stops working, or stops updating, when it lapsesSoftware you keep improving and supporting
Per site or per domainEach licence covers a set number of domainsThemes, plugins and web applications
FreemiumA free core with paid features unlocked by a keyBuilding an audience before selling

Write the terms down in a clear licence agreement. The agreement, not the code, is what gives you a legal remedy if someone breaks the terms.

3. Design licence keys you can verify offline

A random key that is only checked against your server works, but every check depends on your server being up. A better design is a signed licence: a small JSON payload (who bought it, which product, how many domains, expiry date) plus a digital signature made with a private key that exists only on your licence server.

The application carries only the public key. It can confirm that a licence is genuine and unchanged, but it cannot create one. Someone reading your code learns nothing that lets them forge a key.

Signing on your licence server, with OpenSSL (available in nearly every PHP build):

php
<?php
// Run once: create a key pair and keep private.pem off every public server.
// $key = openssl_pkey_new(['private_key_type' => OPENSSL_KEYTYPE_EC, 'curve_name' => 'prime256v1']);
// openssl_pkey_export_to_file($key, 'private.pem');
// file_put_contents('public.pem', openssl_pkey_get_details($key)['key']);

$licence = json_encode([
    'id'      => 'LIC-10492',
    'product' => 'invoice-pro',
    'email'   => '[email protected]',
    'domains' => 1,
    'updates_until' => '2027-09-23',
]);
openssl_sign($licence, $signature, file_get_contents('/secure/private.pem'), OPENSSL_ALGO_SHA256);
$key = base64_encode($licence) . '.' . base64_encode($signature);

Verifying inside the application:

php
<?php
function licence_is_genuine(string $key, string $publicPem): ?array {
    [$payload, $sig] = array_map('base64_decode', explode('.', $key, 2) + [1 => '']);
    if (openssl_verify($payload, $sig, $publicPem, OPENSSL_ALGO_SHA256) !== 1) {
        return null; // forged or altered
    }
    return json_decode($payload, true);
}

The same pattern works with Ed25519 signatures through PHP's sodium functions, but the sodium extension is not included in every host's PHP build, so OpenSSL is the safer default for software that customers install themselves.

4. Activation and ongoing checks

A genuine key can still be shared. Activation limits that.

  1. Activate once.
    On install, the application sends the key and the site's domain to your licence server over HTTPS. The server records the activation and refuses it if the licence has no free slots.
  2. Store the result.
    Save the server's signed activation response locally, so the application does not need to call home on every page load.
  3. Re-check occasionally.
    Validate again every few days, or when an admin opens the settings page, not on every request.
  4. Allow a grace period.
    If your server cannot be reached, keep working for a set number of days and show a notice. An outage on your side should never take a customer's site down.
  5. Let customers move.
    Provide a deactivate button, so a customer changing domain or server can free the slot without contacting you.
Fail gently

When a licence is invalid or expired, disable updates or premium features and show a clear message. Never delete data, lock customers out of their own records or break their website. That damages your reputation and may break consumer law.

5. Build the licence server

The licence server is a small web application with a database. At minimum it needs:

  • Tables for customers, licences (product, limits, expiry, status) and activations (licence, domain, first and last seen).
  • An issue step triggered by your payment system when an order is paid.
  • API endpoints to activate, validate and deactivate, each returning a signed response.
  • Rate limiting on the endpoints, so nobody can guess keys by brute force.
  • An admin view to revoke a refunded or abused licence and see where each key is active.

Keep the private signing key out of the web root and out of version control. If you would rather not build this, hosted licensing services exist; compare their pricing and data location before you commit.

6. Distribute releases and updates

  • Short-lived download links. After payment, and from the customer's account page, generate a download link that expires after a short time and is tied to a valid licence.
  • Versioned releases. Publish each version as a numbered zip with a changelog, and keep older versions available for customers on older PHP versions.
  • Checksums. Publish a SHA-256 checksum for each release, so buyers can confirm the file arrived intact.
  • An update check. Let the application ask your server for the latest version its licence entitles it to, and download it through the same licensed link.
  • Composer, for developer buyers. A private Composer repository, self-hosted with Satis or run as a hosted service, lets developers install your package with their licence key as the credential.

7. Protect the licence check itself

A licence check written in plain PHP can simply be deleted. Encode the files that contain it, and the core logic around it, so that removing the check is not a one-line edit. See Securing self-hosted PHP applications with obfuscation and encoding tools for the current tools and their limits.

8. Running this on Domain India

The licence server. A small PHP and MySQL licence API runs comfortably on shared hosting. If you build it in Node.js, the App Platform detects Node.js apps automatically and includes a PostgreSQL database; other languages need a Dockerfile. For full control, a self-managed VPS gives you root access.

Customer installs on shared hosting. If your buyers may run your application on shared hosting, test the activation call there. Shared servers disable some PHP network functions: on our cPanel servers fsockopen, stream_socket_client and curl_multi_exec are disabled, and on most DirectAdmin sites curl_exec is disabled too. Offline signature checks with a grace period keep your application working even where the call home fails. On our cPanel servers' PHP 8.3 build the sodium extension is not installed (measured 23 September 2026), which is why the example above uses OpenSSL. See PHP disabled functions on shared hosting.

App Starter
₹100/mo + GST
  • 512 MB RAM per app
  • 1 vCPU
  • 5 GB NVMe SSD
  • PostgreSQL Database
See plan details
cPanel Starter
₹125/mo + GST
  • 25 GB NVMe SSD Storage
  • 50 GB Monthly Bandwidth
  • 1 Website
  • 10 Email Accounts
See plan details

Prices on the cards are live and exclude 18% GST.

What is a signed licence key?

It is a small data payload, such as the buyer, product, domain limit and expiry, plus a digital signature made with a private key that only the vendor holds. The application checks the signature with the matching public key, so it can confirm the licence is genuine without being able to create one.

Should my PHP application check the licence on every page load?

No. Activate once, store the signed result, and re-check every few days with a grace period if your licence server cannot be reached. Checking on every request slows the site and makes your outage the customer's outage.

What should happen when a licence is invalid?

Disable updates or premium features and show a clear message. Never delete data or break the customer's website.

How do I stop one licence key being used on many sites?

Tie each activation to a domain on your licence server and refuse new activations once the licence's limit is reached. Give customers a deactivate option so they can move to a new domain.

Can I run a licence server on shared hosting?

A small PHP and MySQL licence API can run on shared hosting. Keep the private signing key outside the web root, and use HTTPS for every request.

Why does my licence activation fail on some shared hosts?

Many shared hosts disable PHP network functions such as fsockopen, stream_socket_client or curl_exec. Test the activation call on the hosts your buyers use, and support offline signature checks with a grace period.

Ready to launch your software? Host your licence server on the App Platform, cPanel hosting or a VPS, and read about protecting your PHP code before you ship.

Host your licence server

Deploy a Node.js licence API with a PostgreSQL database and free SSL on your own domain.

See App Platform plans

Was this article helpful?

Your answer helps us decide what to improve next.

Still need help? Open a support ticket and our team will reply.

Prefer an app? Add this site to your home screen.Get the app