Public Endpoints
Public endpoints are the client-facing API surface that your distributed plugins and themes call at runtime. They handle licence validation, site activation, update checks, secure downloads, and trial provisioning.
Note
All public endpoints are prefixed with /wp-json/wplf/v1/. Authentication is not required for the health check endpoint. All other public endpoints use the licence key as implicit authentication.
Rate limits
Each public endpoint has a per-IP rate limit. When the limit is exceeded, the API returns HTTP 429. See Rate Limiting for configuration details.
| Endpoint | Default limit |
|---|---|
| validate | 30 requests/min |
| activate | 10 requests/min |
| deactivate | 10 requests/min |
| updates/check | 60 requests/min |
| webhooks/stripe | 120 requests/min |
| trials/request | 5 requests/min |
Health check
GET /wplf/v1/health
Returns the current status of the LicenceForge API. No authentication required. Useful for uptime monitoring.
Response
{
"status": "ok",
"version": "3.2.0",
"timestamp": "2026-02-21T10:30:00Z"
}
Validate licence
POST /wplf/v1/licenses/validate
Checks whether a licence key is valid for a given product and site. This is the primary endpoint your client library calls on plugin initialization to determine whether the user holds a valid licence.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
license_key |
string | Yes | The licence key to validate (format: XXXX-XXXX-XXXX-XXXX). |
product_slug |
string | Yes | The unique slug of the product. |
site_url |
string | Yes | The URL of the site making the request. |
server_fingerprint |
string | No | A server-generated fingerprint for device tracking. See Device Fingerprinting. |
Request example
curl -X POST https://example.com/wp-json/wplf/v1/licenses/validate \
-H "Content-Type: application/json" \
-d '{
"license_key": "A1B2-C3D4-E5F6-G7H8",
"product_slug": "jetwoo-builder",
"site_url": "https://clientsite.com"
}'
Response (200 OK)
{
"valid": true,
"status": "active",
"expires": "2027-02-21T00:00:00Z",
"activation_limit": 5,
"activation_count": 2,
"already_activated": true,
"product_version": "2.4.1",
"is_trial": false,
"trial_ends": null,
"tier": {
"label": "Professional",
"features": ["priority-support", "advanced-templates", "white-label"]
}
}
Error response (400)
{
"code": "invalid_license_key",
"message": "The licence key provided is not valid.",
"data": {
"status": 400
}
}
Activate licence
POST /wplf/v1/licenses/activate
Activates a licence for a specific site URL. This registers the site against the licence and counts toward the activation limit. If the site is already activated, the endpoint returns the existing activation without consuming an additional slot.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
license_key |
string | Yes | The licence key to activate. |
product_slug |
string | Yes | The product slug. |
site_url |
string | Yes | The URL of the site to activate. |
server_fingerprint |
string | No | Server fingerprint for device tracking. |
Request example
curl -X POST https://example.com/wp-json/wplf/v1/licenses/activate \
-H "Content-Type: application/json" \
-d '{
"license_key": "A1B2-C3D4-E5F6-G7H8",
"product_slug": "jetwoo-builder",
"site_url": "https://clientsite.com",
"server_fingerprint": "d4e5f6a7b8c9"
}'
Response (200 OK)
{
"activated": true,
"activation_id": 147,
"site_url": "https://clientsite.com",
"activation_count": 3,
"activation_limit": 5,
"activated_at": "2026-02-21T10:45:00Z"
}
Error response (403)
{
"code": "activation_limit_reached",
"message": "This licence has reached its activation limit (5/5). Deactivate an existing site before activating a new one.",
"data": {
"status": 403,
"activation_limit": 5,
"activation_count": 5
}
}
Deactivate licence
POST /wplf/v1/licenses/deactivate
Removes a site activation from a licence, freeing up the activation slot for reuse.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
license_key |
string | Yes | The licence key. |
product_slug |
string | Yes | The product slug. |
site_url |
string | Yes | The URL of the site to deactivate. |
Request example
curl -X POST https://example.com/wp-json/wplf/v1/licenses/deactivate \
-H "Content-Type: application/json" \
-d '{
"license_key": "A1B2-C3D4-E5F6-G7H8",
"product_slug": "jetwoo-builder",
"site_url": "https://clientsite.com"
}'
Response (200 OK)
{
"deactivated": true,
"site_url": "https://clientsite.com",
"activation_count": 2,
"activation_limit": 5
}
Check for updates
GET /wplf/v1/updates/check
Checks whether a newer version of a product is available. This endpoint integrates with the WordPress update system so your plugin or theme appears in the standard Dashboard > Updates screen.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
product_slug |
string | Yes | The product slug. |
license_key |
string | Yes | The licence key for authentication and rollout bucketing. |
current_version |
string | Yes | The version currently installed (semver format). |
site_url |
string | Yes | The URL of the requesting site. |
Request example
curl "https://example.com/wp-json/wplf/v1/updates/check?\
product_slug=jetwoo-builder&\
license_key=A1B2-C3D4-E5F6-G7H8&\
current_version=2.3.0&\
site_url=https://clientsite.com"
Response (200 OK)
{
"new_version": "2.4.1",
"url": "https://example.com/product/jetwoo-builder/",
"package": "https://example.com/wp-json/wplf/v1/downloads/jetwoo-builder?token=eyJhbGciOi...",
"package_hash": "sha256:a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c3d2e1f0a9b8",
"tested": "6.7",
"requires": "6.2",
"requires_php": "7.4",
"rollout": {
"percentage": 50,
"in_rollout": true
},
"sections": {
"changelog": "<h4>2.4.1</h4><ul><li>Fixed compatibility issue with WooCommerce 9.x</li><li>Improved performance of template rendering</li></ul>"
}
}
Tip
When no update is available (the installed version is current), the response returns an empty object {} with a 200 status code. If the licence is within a staggered rollout but not yet in the eligible bucket, the rollout.in_rollout field will be false and no package URL is included.
Download product
GET /wplf/v1/downloads/{product_slug}
Serves the product download file. This endpoint is called by WordPress during the update process using the package URL returned by the update check. Authentication is handled via a signed, time-limited download token.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
product_slug |
string (path) | Yes | The product slug (in the URL path). |
token |
string (query) | Yes | A signed download token generated by the update check endpoint. |
Request example
curl -L "https://example.com/wp-json/wplf/v1/downloads/jetwoo-builder?token=eyJhbGciOi..." \
-o jetwoo-builder.zip
Response
On success, the endpoint either serves the ZIP file directly (for locally stored packages) or issues a 302 redirect to the external download URL (for S3 or CDN-hosted files). The Content-Type header is set to application/zip for direct downloads.
Error response (403)
{
"code": "invalid_download_token",
"message": "The download token is invalid or has expired.",
"data": {
"status": 403
}
}
Stripe webhook
POST /wplf/v1/webhooks/stripe
Receives incoming webhook events from Stripe. This endpoint is configured in your Stripe dashboard and processes payment events to create, renew, and cancel licences automatically. See Webhooks for full details on event handling, signature verification, and retry behaviour.
Configuration
Configure this URL in your Stripe webhook settings:
https://yoursite.com/wp-json/wplf/v1/webhooks/stripe
Warning
Do not call this endpoint manually. It requires a valid Stripe signature header (Stripe-Signature) and will reject unsigned requests.
Request trial
POST /wplf/v1/trials/request
Provisions a trial licence for a prospective customer. Trials are limited to one per email address per product. The trial duration and activation limit are configured on the product.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
product_slug |
string | Yes | The product slug. |
email |
string | Yes | The email address of the prospective customer. |
name |
string | No | The customer name (used in notification emails). |
Request example
curl -X POST https://example.com/wp-json/wplf/v1/trials/request \
-H "Content-Type: application/json" \
-d '{
"product_slug": "jetwoo-builder",
"email": "[email protected]",
"name": "Jane Smith"
}'
Response (201 Created)
{
"license_key": "T1R2-I3A4-L5K6-E7Y8",
"product_slug": "jetwoo-builder",
"status": "trial",
"expires": "2026-03-07T00:00:00Z",
"activation_limit": 1,
"is_trial": true,
"trial_ends": "2026-03-07T00:00:00Z"
}
Error response (409)
{
"code": "trial_already_used",
"message": "A trial licence has already been issued for this email address and product.",
"data": {
"status": 409
}
}
Note
Trial requests are rate-limited to 5 per minute per IP to prevent abuse. The trial licence key is also sent to the provided email address via the configured email template.