Non-WordPress Integration

LicenceForge's REST API can be consumed by any HTTP client. This page covers raw HTTP integration for applications that do not run on WordPress, including cURL, plain PHP, and other languages.

Note

All endpoints described here are public-facing and documented in Public Endpoints. If your LicenceForge installation has Require API Key enabled (wplf_require_api_key = yes), you must include the X-LicenceForge-Key header in every request.

Authentication

If API key authentication is enabled on the server, include the key as a request header:

X-LicenceForge-Key: lf_pk_your_public_key_here

This header is required on all public endpoints when wplf_require_api_key is set to yes in your LicenceForge settings. If the setting is disabled, the header is ignored and can be omitted.

Validate a licence

POST /wp-json/wplf/v1/licenses/validate

Request body

{
  "license_key": "XXXX-XXXX-XXXX-XXXX",
  "product_slug": "my-product",
  "site_url": "https://example.com"
}
Field Type Required Description
license_key string Yes The licence key to validate.
product_slug string Yes The product slug this licence belongs to.
site_url string Yes The URL of the site requesting validation.

Response (200 OK)

{
  "valid": true,
  "status": "active",
  "expires": "2025-12-31T23:59:59",
  "activation_limit": 5,
  "activation_count": 1,
  "tier": {
    "label": "Pro",
    "features": [
      "premium-support",
      "advanced-forms",
      "pdf-export"
    ]
  }
}

Activate a licence

POST /wp-json/wplf/v1/licenses/activate

Request body

{
  "license_key": "XXXX-XXXX-XXXX-XXXX",
  "product_slug": "my-product",
  "site_url": "https://example.com"
}

The request body uses the same fields as the validation endpoint. On success, the server registers the site URL as an active activation slot for the licence.

Response (200 OK)

{
  "activated": true,
  "status": "active",
  "activation_count": 2,
  "activation_limit": 5
}

Deactivate a licence

POST /wp-json/wplf/v1/licenses/deactivate

Request body

{
  "license_key": "XXXX-XXXX-XXXX-XXXX",
  "product_slug": "my-product",
  "site_url": "https://example.com"
}

On success, the server removes the site URL from the licence's activation list, freeing the slot for use on another site.

Response (200 OK)

{
  "deactivated": true,
  "activation_count": 1,
  "activation_limit": 5
}

Check for updates

GET /wp-json/wplf/v1/updates/check

Query parameters

Parameter Type Required Description
product_slug string Yes The product slug to check for updates.
license_key string Yes The licence key authorising the update check.
current_version string Yes The currently installed version (e.g. 2.4.1).
site_url string Yes The URL of the site requesting the update.

Example request URL

https://licences.example.com/wp-json/wplf/v1/updates/check?product_slug=my-product&license_key=XXXX-XXXX-XXXX-XXXX&current_version=2.4.1&site_url=https://example.com

Response (200 OK) -- update available

{
  "update_available": true,
  "new_version": "2.5.0",
  "package": "https://licences.example.com/wplf/v1/downloads/my-product?token=eyJ0eXAi...",
  "package_hash": "sha256:a3f8c2d1e4b5a6f7...",
  "changelog": "Added conditional logic builder. Fixed form submission race condition.",
  "requires_php": "7.4"
}

Response (200 OK) -- no update

{
  "update_available": false,
  "current_version": "2.5.0"
}

cURL example

The following cURL command validates a licence. Replace the URL and values with your own.

curl -X POST "https://licences.example.com/wp-json/wplf/v1/licenses/validate" \
  -H "Content-Type: application/json" \
  -H "X-LicenceForge-Key: lf_pk_your_public_key" \
  -d '{
    "license_key": "A1B2-C3D4-E5F6-G7H8",
    "product_slug": "my-product",
    "site_url": "https://example.com"
  }'

PHP example (without WordPress)

For PHP applications that do not have WordPress loaded, use file_get_contents() or any HTTP library.

$api_url = 'https://licences.example.com/wp-json/wplf/v1/licenses/validate';

$payload = json_encode( [
    'license_key'  => 'A1B2-C3D4-E5F6-G7H8',
    'product_slug' => 'my-product',
    'site_url'     => 'https://example.com',
] );

$context = stream_context_create( [
    'http' => [
        'method'  => 'POST',
        'header'  => implode( "\r\n", [
            'Content-Type: application/json',
            'X-LicenceForge-Key: lf_pk_your_public_key',
        ] ),
        'content' => $payload,
        'timeout' => 15,
    ],
] );

$response = file_get_contents( $api_url, false, $context );

if ( $response === false ) {
    // Handle connection error
    die( 'Failed to connect to licence server.' );
}

$data = json_decode( $response, true );

if ( $data['valid'] ) {
    echo 'Licence is active. Tier: ' . $data['tier']['label'];
} else {
    echo 'Licence is not valid. Status: ' . $data['status'];
}

Error responses

All endpoints return standard HTTP status codes with a JSON error body on failure.

Code Meaning Common cause
400 Bad Request Missing required field (license_key, product_slug, or site_url).
401 Unauthorized Missing or invalid X-LicenceForge-Key header when API key is required.
403 Forbidden Licence key is suspended or cancelled.
404 Not Found Licence key or product slug does not exist.
409 Conflict Activation limit reached (all activation slots in use).
429 Too Many Requests Rate limit exceeded. See Rate Limiting.

Error response body

{
  "code": "license_not_found",
  "message": "No licence was found matching the provided key and product.",
  "status": 404
}

Future packages

Note

Official Composer and NPM packages for LicenceForge client integration are under consideration for a future release. These packages would wrap the HTTP endpoints described above and provide idiomatic interfaces for PHP (non-WordPress) and Node.js applications. For now, use the raw HTTP endpoints directly.

Next steps