The API included with PaddlePress allows you to remotely activate license keys, check if keys are valid, and retrieve information about the latest version of the software.
It specially designed to provide auto-update functionality to WordPress products.
License Endpoint #
There are three action types available in this endpoint.
Info | Used to remotely check if a license key is activated, valid, and not expired |
Activate | Used to remotely activate a license key |
Deactivate | Used to remotely deactivate a license key |
https://example.org/wp-json/paddlepress-api/v1/license?license_key=7e60d6af-550a-d9a9-dfa6-25b2de37fe63&license_url=http://example.test&action=info
Request parameters:
action | supported actions: info, activate, deactivate | required |
license_key | the license key you are performing an action for | required |
license_url | the license URL you are performing to action for | required |
download_tag | the slug of a downloadable item | optional |
The response for these requests will be a JSON object. If the license has been successfully activated for provided domain, the response will be something like:
{
"expires": "2021-01-05",
"payment_id": "2",
"license_limit": 10,
"site_count": 4,
"activations_left": 6,
"success": true,
"license_status": "valid",
"errors": []
}
If the license is invalid, the response will be
{
"expires": "lifetime",
"payment_id": null,
"license_limit": 0,
"site_count": 0,
"activations_left": 0,
"success": false,
"license_status": "invalid",
"errors": {
"missing_license_key": [
"License key does not exist"
]
}
}
Possible errors:
missing_license_key - License key does not exist
expired_license_key - License key has expired
unregistered_license_domain - The domain is not activated for provided key
invalid_license_or_domain - Wrong license_url or license_key
can_not_add_new_domain - Can't register provided license_url due to activation limits.
blocked_license_domain - Blocked domain address for the given license key.
Update Endpoint #
The update endpoint has designed for the auto-update functionality.
https://example.test/wp-json/paddlepress-api/v1/update?action=get_version&license_key=7e60d6af-550a-d9a9-dfa6-25b2de37fe63&license_url=http://example.test&download_tag=hello-dolly&beta=1
The request parameters:
action | Supported actions: get_version, plugin_information, theme_information, download | required |
license key | The license key you are performing an action for | required for restricted downloads. |
license_url | The license URL you are performing to action for | required for restricted downloads. |
download_tag | The the slug of a downloadable item. | required |
beta | If you wish to check beta version | optional |
The response object for “get_version” requests:
{
"id": 4550,
"new_version": "0.2.0",
"stable_version": "0.2.0",
"name": "dummy-plugin",
"slug": "dummy-plugin",
"last_updated": "2020-12-18 11:27am GMT",
"sections": {
"description": "...",
"faq": "...",
"changelog": "<h4>1.0</h4>\n\n<ul>\n<li>A change since the previous version.</li>\n<li>Another change.</li>\n</ul>\n\n<h4>0.5</h4>\n\n<ul>\n<li>List versions from most recent at top to oldest at bottom.</li>\n</ul>"
},
"url": "https://example.org/ppp_download/dummy-plugin-2-beta/?changelog=1",
"banners": {
"2x": "https://ps.w.org/dummy-plugin/assets/banner-1544x500.png?rev=1633163",
"1x": "https://ps.w.org/dummy-plugin/assets/banner-772x250.png?rev=1633163"
},
"icons": {
"2x": "https://ps.w.org/dummy-plugin/assets/icon-256x256.jpg?rev=1633163",
"1x": "https://ps.w.org/dummy-plugin/assets/icon-256x256.jpg?rev=1633163"
},
"package": "https://example.org/wp-json/paddlepress-api/v1/update?action=download&download_tag=dummy-plugin&beta=1&license_key=7e60d6af-550a-d9a9-dfa6-25b2de37fe63&license_url=http://example.test",
"download_link": "https://example.org/wp-json/paddlepress-api/v1/update?action=download&download_tag=dummy-plugin&beta=1&license_key=7e60d6af-550a-d9a9-dfa6-25b2de37fe63&license_url=http://example.test"
}
The response object for “plugin_information” and “theme_information” requests:
{
"name": "dummy-plugin",
"slug": "dummy-plugin",
"version": "0.2.0",
"new_version": "1.2.8",
"requires": "4.5",
"requires_php": "5.6",
"tested": "5.6",
"stable_tag": "0.2.0",
"donate_link": "https://example.com/",
"sections": {
"description": "...",
"installation": "...",
"faq": "...",
"changelog": "..."
},
"description": "<p>This is the long description. No limit, and you can use Markdown (as well as in the following sections).",
"downloaded": 1,
"banners": {
"low": "https://ps.w.org/dummy-plugin/assets/banner-772x250.png?rev=1633163",
"high": "https://ps.w.org/dummy-plugin/assets/banner-1544x500.png?rev=1633163"
},
"icons": {
"low": "https://ps.w.org/dummy-plugin/assets/icon-256x256.jpg?rev=1633163",
"high": "https://ps.w.org/dummy-plugin/assets/icon-256x256.jpg?rev=1633163"
},
"author": "<a href=\"https://example.org\" rel=\"noopener\">Example Author</a>",
"last_updated": "2020-12-15 9:17pm GMT",
"package": "https://example.test/wp-json/paddlepress-api/v1/update?action=download&download_tag=dummy-plugin&license_key=5878a827-83b8-bb33-e652-e5c837fe1ab4&license_url=fastpay.test",
"download_link": "https://example.test/wp-json/paddlepress-api/v1/update?action=download&download_tag=dummy-plugin&license_key=5878a827-83b8-bb33-e652-e5c837fe1ab4&license_url=fastpay.test"
}
With version 2.4 deactivation endpoint will return success=>true
for local development domains. However, their status will remain activated if your settings allows to use of local domain addresses.
API Rate Limiting #
Enable this option to prevent excessive API requests from the same IP address. It’s particularly useful to block abusive behaviors, such as automated license key guessing or brute-force attacks on your update endpoints.
How It Works #
- When enabled, each IP address is tracked using a transient-based counter.
- The limit is enforced using a sliding 60-second window:
- Each valid request increments a counter and resets the timer.
- If the number of requests from the same IP reaches the configured limit within that sliding window, further requests will be blocked for 60 seconds.
- Blocked requests will receive an HTTP 429: Too Many Requests error response.
Example #
If the limit is set to 5
:
- The first request from an IP starts a 60-second timer.
- Each request resets the 60-second countdown and increases the count.
- If 5 or more requests are made in quick succession, the next ones will be denied until a full 60 seconds pass without a new request.
Note: This uses a sliding window, meaning the cooldown period moves forward with each request. It’s a lightweight method ideal for general abuse prevention.