How to integrate purchase-code licensing and product updates
License API overview
Authors can protect their applications by validating a customer purchase code against the DigiMarket API. Each request must use the author's API key from the author account. The API binds the license to the installation identity built from server IP, domain, site URL or an explicit machine ID.
Endpoints
POST /api/license-manager/purchase/verifyverifies, activates or deactivates a purchase code.POST /api/license-manager/updates/checkchecks if an approved patch or full product package is available.GET|POST /api/license-manager/updates/{release}/downloaddownloads the approved update package only when the license is valid for that server.
PHP activation
$payload = [
'action' => 'activate',
'purchase_code' => $purchaseCode,
'product_token' => 'your-product-slug',
'server_ip' => $_SERVER['SERVER_ADDR'] ?? '',
'server_host' => $_SERVER['HTTP_HOST'] ?? '',
'site_url' => 'https://' . ($_SERVER['HTTP_HOST'] ?? ''),
'platform' => 'php',
'app_version' => '1.0.0',
];
$ch = curl_init('https://your-marketplace.com/api/license-manager/purchase/verify');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_AUTHOR_API_KEY',
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
JavaScript server-side example
const response = await fetch("https://your-marketplace.com/api/license-manager/purchase/verify", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_AUTHOR_API_KEY",
"Accept": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
action: "activate",
purchase_code: purchaseCode,
product_token: "your-product-slug",
server_ip: request.ip,
server_host: request.hostname,
site_url: `https://${request.hostname}`,
platform: "node",
app_version: "1.0.0"
})
});
const data = await response.json();
Python example
import requests
data = requests.post(
"https://your-marketplace.com/api/license-manager/purchase/verify",
json={
"action": "activate",
"purchase_code": purchase_code,
"product_token": "your-product-slug",
"server_ip": server_ip,
"server_host": server_host,
"site_url": site_url,
"platform": "python",
"app_version": "1.0.0",
},
headers={"Authorization": "Bearer YOUR_AUTHOR_API_KEY", "Accept": "application/json"},
timeout=20,
).json()
Windows C++ desktop installer example
#include <windows.h>
#include <winhttp.h>
#include <string>
// Link with winhttp.lib.
// This minimal example shows the request shape. Production apps should add
// robust JSON parsing, TLS error handling and retry limits.
std::wstring apiHost = L"your-marketplace.com";
std::wstring apiPath = L"/api/license-manager/purchase/verify";
std::string body =
"{\"action\":\"activate\","
"\"purchase_code\":\"CUSTOMER-PURCHASE-CODE\","
"\"product_token\":\"your-product-slug\","
"\"machine_id\":\"WINDOWS-MACHINE-FINGERPRINT\","
"\"platform\":\"windows-cpp\","
"\"app_version\":\"1.0.0\"}";
HINTERNET session = WinHttpOpen(L"YourApp/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
HINTERNET connect = WinHttpConnect(session, apiHost.c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0);
HINTERNET request = WinHttpOpenRequest(connect, L"POST", apiPath.c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
std::wstring headers =
L"Authorization: Bearer YOUR_AUTHOR_API_KEY\r\n"
L"Accept: application/json\r\n"
L"Content-Type: application/json\r\n";
WinHttpSendRequest(request, headers.c_str(), (DWORD)-1L, (LPVOID)body.c_str(), (DWORD)body.size(), (DWORD)body.size(), 0);
WinHttpReceiveResponse(request, NULL);
// Read the response body and continue only when the JSON contains valid=true.
Linux shell / installable app example
curl -X POST "https://your-marketplace.com/api/license-manager/purchase/verify" \
-H "Authorization: Bearer YOUR_AUTHOR_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"action":"activate",
"purchase_code":"CUSTOMER-PURCHASE-CODE",
"product_token":"your-product-slug",
"machine_id":"'$(cat /etc/machine-id 2>/dev/null)'",
"server_ip":"'$(hostname -I | awk "{print \$1}")'",
"server_host":"'$(hostname -f)'",
"platform":"linux",
"app_version":"1.0.0"
}'
C# / .NET installer example
using System.Net.Http;
using System.Net.Http.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_AUTHOR_API_KEY");
client.DefaultRequestHeaders.Add("Accept", "application/json");
var response = await client.PostAsJsonAsync(
"https://your-marketplace.com/api/license-manager/purchase/verify",
new {
action = "activate",
purchase_code = purchaseCode,
product_token = "your-product-slug",
machine_id = Environment.MachineName,
platform = "dotnet",
app_version = "1.0.0"
}
);
var json = await response.Content.ReadAsStringAsync();
Go command-line application example
payload := strings.NewReader(`{
"action":"activate",
"purchase_code":"CUSTOMER-PURCHASE-CODE",
"product_token":"your-product-slug",
"machine_id":"SERVER-FINGERPRINT",
"platform":"go",
"app_version":"1.0.0"
}`)
req, _ := http.NewRequest("POST", "https://your-marketplace.com/api/license-manager/purchase/verify", payload)
req.Header.Set("Authorization", "Bearer YOUR_AUTHOR_API_KEY")
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
Update check
The update API returns update_mode as patch when a patch package exists, or full when the customer must download and reinstall the complete product package. Authors always upload the complete product package for every update. A patch ZIP is optional and is served only when it exists and the release has been approved by an admin or reviewer.
{
"purchase_code": "CUSTOMER-PURCHASE-CODE",
"product_token": "your-product-slug",
"current_version": "1.0.0",
"server_ip": "203.0.113.10",
"server_host": "example.com",
"site_url": "https://example.com"
}
Update response shape
{
"valid": true,
"update_available": true,
"update_mode": "patch",
"patch_available": true,
"full_required": false,
"release": {
"version": "1.2.0",
"download_url": "https://your-marketplace.com/api/license-manager/updates/12/download?package=patch",
"patch_package": {"file_name": "patch-1.2.0.zip"},
"full_package": {"file_name": "product-1.2.0.zip"}
}
}