Documentation

Everything you need to integrate and run Licensify.

Overview

Licensify lets you validate license keys by domain. A client (e.g. WordPress plugin, SaaS app) sends license_key and domain to POST /api/validate-license and receives success or error. The server checks key validity, expiry, and domain binding. First successful validation can bind the license to that domain.

Base URL: https://licensify.mkbuilds.live. All API responses are JSON. Send Accept: application/json for validation error responses in JSON.

API Reference

Validate license

Check whether a license key is valid for a given domain.

  • Endpoint: POST https://licensify.mkbuilds.live/api/validate-license
  • Rate limit: 10 requests per minute per IP
  • Auth: None (public endpoint for client validation)

Request

Content-Type: application/x-www-form-urlencoded or application/json.

Parameter Type Required Description
license_keystringYesThe license key
domainstringYesDomain to validate (e.g. example.com or www.example.com). Normalized server-side (lowercase, no protocol/path, www stripped)

Responses

Success

Status: 200 OK

{
  "status": "success",
  "message": "License validation successful"
}

Validation failed (invalid/expired/wrong domain)

Status: 403 Forbidden

{
  "status": "error",
  "message": "License validation failed"
}

Invalid input (e.g. missing domain)

Status: 422 Unprocessable Entity

{
  "message": "Domain is required.",
  "errors": {
    "domain": ["Domain is required."]
  }
}

Behavior

  • If the license has no domain set, the first successful validation binds the license to the given domain.
  • Subsequent validations must use the same (normalized) domain.
  • Domains are normalized: same effective domain (e.g. example.com vs www.example.com) is treated as one.
  • Expired or inactive licenses return the same generic error for security (no enumeration).

Examples

cURL:

curl -X POST https://licensify.mkbuilds.live/api/validate-license \
  -H "Accept: application/json" \
  -d "license_key=XXXX-XXXX-XXXX-XXXX" \
  -d "domain=example.com"

PHP (WordPress / plain PHP):

$response = wp_remote_post($url . '/api/validate-license', [
    'timeout' => 15,
    'body'    => [
        'license_key' => $license_key,
        'domain'      => parse_url(home_url(), PHP_URL_HOST),
    ],
]);
$code = wp_remote_retrieve_response_code($response);
$body = json_decode(wp_remote_retrieve_body($response), true);
$valid = ($code === 200 && isset($body['status']) && $body['status'] === 'success');

A drop-in PHP helper with caching is available in the repo: docs/wordpress-license-client.php. Use it in your plugin to validate licenses and cache the result (e.g. 24h).

Other API routes

  • GET /api/user — Returns the authenticated user (Sanctum). Requires Authorization: Bearer <token>.

What works today

Feature Status
License validation APIWorking
Domain binding (first-use locks to domain)Working
Expiry checkingWorking
Active/inactive toggleWorking
Filament admin panel (create/edit licenses)Working
API rate limiting (60 req/min general; 10/min on validate)Present
CORS enabled for APIPresent

Implemented

The following items from the production checklist are already in place:

  • Input validationlicense_key and domain validated via Form Request
  • Domain normalization — Strip protocol, path, port; lowercase; www stripped so www.example.com = example.com
  • Stricter rate limiting — 10 requests per minute per IP on /api/validate-license
  • Generic error messages — Single “License validation failed” for all failure cases; detailed reason logged server-side
  • Auto-generate license keys — In Filament Create License, leave key empty to get format XXXX-XXXX-XXXX-XXXX
  • WordPress client helperdocs/wordpress-license-client.php with caching and clear usage
  • Activation audit loglicense_activations table; every validation (success/failure) logged; viewable in Filament per license
  • API documentation — This page
  • Automated tests — Feature tests for valid key, invalid key, expired, inactive, domain mismatch, domain normalization, validation errors

Remaining gaps

Consider adding these for production or commercial use:

  • License deactivation / transfer — Customer moves site; license is bound to old domain. Add “Deactivate” or “Reset domain” in admin, or customer-facing deactivation with verification.
  • Product / version support — Single product only. Add product_id or product_slug to licenses and optional product param on validate for multi-product licensing.
  • Updates endpoint — Add GET /api/check-updates?license_key=...&domain=...¤t_version=... returning latest version and download URL if valid (for plugin update checks).
  • Customer self-service portal — Let customers view their licenses and deactivate for transfer (e.g. login with license_key + email or integrate with store).

Nice-to-have (later)

Item Description
Email notificationsNotify on license expiry, first activation, deactivation
License tiersDifferent limits (e.g. sites count, features)
Webhook on validationNotify external systems (CRM, analytics)
Soft delete licensesKeep history instead of hard delete
HTTPS enforcementForce SSL in production
Environment configAPP_DEBUG=false, proper APP_URL for production

WordPress integration checklist

To use this server with a WordPress plugin (e.g. M-Pesa plugin):

  1. Add license settings in the plugin: license key input, “Activate” / “Deactivate” buttons.
  2. On activation: POST to https://licensify.mkbuilds.live/api/validate-license with license_key and domain (from site_url() or parse_url(home_url(), PHP_URL_HOST)).
  3. Cache result (transient, 12–24h) to avoid repeated API calls.
  4. Gate features: If validation fails, show “License required” and limit functionality.
  5. Optional: Periodic re-validation (e.g. weekly cron) or on plugin load.

Use the provided docs/wordpress-license-client.php helper: instantiate with your API URL and product slug, call validate($license_key, $domain), and optionally clearCache() on deactivation.

Recommended priority order

If you are implementing remaining items, this order is suggested:

  1. Input validation — Implemented
  2. Domain normalization — Implemented
  3. Stricter rate limiting on validate — Implemented (10/min)
  4. Generic error messages — Implemented
  5. Auto-generate license keys — Implemented
  6. WordPress client helper — Implemented
  7. Activation audit log — Implemented
  8. API documentation — Implemented
  9. License deactivation / transfer
  10. Automated tests — Implemented

Conclusion

Licensify is functional and suitable for internal or early use. Critical items (validation, domain normalization, security, client integration) are implemented. Remaining gaps (deactivation, multi-product, updates endpoint, customer portal) will make it more robust for commercial sale. With the current implementation you can create accounts, generate license keys, validate them via API, and view activation history in the dashboard.