License Open API Document

v1.0

License Open API Document

This document is for developers who need to integrate a complete "pay → issue → activate → verify" flow into their own software (client software / promotion-only products). Each API below is described with its call timing, request parameters, response fields, and error codes.

1. Core Concepts

Concept Field / Term Description
Software API secret licenseApiSecret Automatically generated when the product enables "license activation". Visible in the product edit form in the Developer Center. Your software server uses it to compute the HMAC signature and the platform uses it to verify. Store it only on your server; never embed it in the client.
License code licenseCode A unique code generated by the platform. Users activate your software with it.
Machine code machineCode A device identifier generated by the client software (unique per computer; hash a stable machine fingerprint, at least 8 characters).
Activation token activationToken Issued by the platform during activation / code generation. The software stores it and sends it back on every startup verification.
Client order ID clientOrderId The order ID of the in-software payment (generated by the client or your server). The platform deduplicates by "product + order ID" to prevent duplicate charges or duplicate code issuance.

2. Preparation

  1. Enable "license activation" when publishing the product and save the generated Software API secret (licenseApiSecret);
  2. Configure the edition list (e.g. BASIC/PRO/ULTIMATE) and the upgrade strategy (SAME_CODE = upgrade in place / NEW_CODE = issue a new code) in the publish form;
  3. Keep the secret on your software server; the client only keeps the license code and the activation token.

3. API Overview

Base path: https://www.powersoftware.app/frontApi (replace with your deployment domain for local / test environments).

API When to call Authentication Signature
POST /license/software/generate Right after an in-software payment succeeds None (signature verified) Required
POST /license/software/upgrade Right after a renewal / edition upgrade payment succeeds None (signature verified) Required
POST /license/activate User first activation / switching to a new device None Not required
POST /license/verify Every time the software starts None Not required
POST /license/deactivate User unbinds the old device (Profile Center) Login Not required

4. Signature Rules (required for generate / upgrade)

Payload: concatenate the following fields in this exact order with newline characters (\n). For missing optional fields use empty values (edition empty string, expiryDays = 0):

productId \n machineCode \n edition \n expiryDays \n clientOrderId \n licenseCode \n timestamp

Signature: HMAC-SHA256(Software API secret licenseApiSecret, payload), Base64URL-encoded, and put into the signature field.

Replay protection: timestamp is a millisecond timestamp. The platform requires it to be within 5 minutes of the server time, otherwise signatureInvalid is returned.

Node.js example:

const crypto = require("crypto");
const payload = [productId, machineCode, edition, expiryDays, clientOrderId, licenseCode, timestamp].join("\n");
const signature = crypto.createHmac("sha256", API_SECRET).update(payload).digest("base64url");

Python example:

import hashlib, hmac, base64
payload = "\n".join([str(productId), machineCode, edition, str(expiryDays), clientOrderId, licenseCode, str(timestamp)])
signature = base64.urlsafe_b64encode(hmac.new(API_SECRET.encode(), payload.encode(), hashlib.sha256).digest()).decode().rstrip("=")

(Base64URL is standard Base64 with + replaced by -, / replaced by _, and trailing = padding removed.)

5. API Details

5.1 Generate a License Code (call after in-software payment)

When to call: right after the user finishes an in-software payment, your server calls this once and stores the returned license code and activation token. The same order should be sent only once; repeated calls are idempotent and will not issue another code.

POST /license/software/generate

Request parameters (JSON body):

Parameter Type Required Source Description
productId number Yes Hard-coded / server config Product ID, matching the product published on the platform
machineCode string Yes Client-generated Machine code of the current device, at least 8 characters
edition string No Chosen by the client at payment Edition ID; must be in the product edition list; defaults to the first edition of the product
expiryDays number No Chosen by the client at payment Validity in days, 0 = permanent; range 0-3650
clientOrderId string Yes Client / server-generated In-software payment order ID, 1-64 characters; idempotency key
timestamp number Yes Server-generated Millisecond timestamp
signature string Yes Server-computed HMAC signature, at least 10 characters

Response content fields:

Field Type Description
licenseId number License record ID
licenseCode string The license code (write it into your license data)
productId number Product ID
edition string Edition ID
machineId number Bound machine record ID
activatedAt string Activation time (ISO8601)
expiryTime string/null Expiry time (ISO8601), null = permanent
maxMachines number Maximum number of bindable machines
activationToken string Activation token; store it for startup verification

Response example:

{
  "code": "SUCCESS",
  "requestId": "xxx",
  "success": true,
  "content": {
    "licenseId": 1001,
    "licenseCode": "AB12-CD34-EF56-GH78",
    "productId": 88,
    "edition": "PRO",
    "machineId": 2001,
    "activatedAt": "2026-08-05T10:00:00.000Z",
    "expiryTime": "2027-08-05T10:00:00.000Z",
    "maxMachines": 1,
    "activationToken": "eyJhbGciOiJIUzI1NiJ9..."
  }
}

Error codes for this API: productIdRequired, machineCodeInvalid, orderIdRequired, productNotFound, productNotEnabled, apiSecretMissing, signatureInvalid, orderAlreadyUsed.

5.2 Upgrade Edition / Renew (call after payment)

When to call: after the user completes a renewal or an edition-upgrade payment. The same order should be sent only once.

POST /license/software/upgrade

Request parameters (JSON body):

Parameter Type Required Source Description
productId number Yes Hard-coded / server config Product ID
licenseCode string Yes Stored in the software Current license code, at least 10 characters
machineCode string No Client-generated Current machine code; pass it when migrating bindings (NEW_CODE strategy) or binding an extra machine
edition string Yes Chosen by the client at payment Target edition ID
expiryDays number No Chosen by the client at payment Additional validity in days, 0 = permanent; range 0-3650
clientOrderId string Yes Client / server-generated Order ID of this purchase; idempotency key
timestamp number Yes Server-generated Millisecond timestamp
signature string Yes Server-computed HMAC signature

Handling strategy (determined by the product configuration):

  • SAME_CODE (upgrade in place): the license code stays the same, machine bindings stay valid, and the validity is extended (a permanent license stays permanent). The response adds upgraded: true to the fields of 5.1;
  • NEW_CODE (issue a new code): the old code is revoked, a new code is issued, and machine bindings are migrated. The response additionally returns oldLicenseId, and licenseCode is the new code.

Response content fields: same as 5.1, plus upgraded: true; under NEW_CODE the response also returns oldLicenseId (the old license record ID; the old code has been revoked).

Error codes for this API: productIdRequired, licenseCodeRequired, orderIdRequired, productNotFound, productNotEnabled, apiSecretMissing, signatureInvalid, codeNotFound, revoked, orderAlreadyUsed, editionRequired.

5.3 Activate a License (first activation / new device)

When to call: after the user obtains a license code (self-service issuance, admin issuance, etc.) and enters it on the activation page of the client software; call it on the new device when the user switches machines.

POST /license/activate

Request parameters (JSON body):

Parameter Type Required Source Description
licenseCode string Yes User input License code, at least 10 characters
machineCode string Yes Client-generated Machine code of the current device, at least 8 characters

Response content: same as 5.1 (licenseId, licenseCode, productId, edition, machineId, activatedAt, expiryTime, maxMachines, activationToken).

Notes:

  • A license code can be bound to multiple machines, limited by maxMachines (defaults to the product configuration);
  • Activating the same machine again reuses the existing binding and re-issues an activation token (idempotent);
  • Failed activations are rate-limited per IP + license code; too many failures return tooManyAttempts.

Error codes for this API: codeNotFound, revoked, expired, machineLimit, tooManyAttempts.

5.4 Verify a License (every software startup)

When to call: every time the software starts (or before unlocking features). The software must store the activationToken returned by 5.1 / 5.2 / 5.3.

POST /license/verify

Request parameters (JSON body):

Parameter Type Required Source Description
licenseCode string Yes Stored in the software License code, at least 10 characters
machineCode string Yes Client-generated Machine code of the current device, at least 8 characters
activationToken string Yes Issued by the platform, stored by the software Activation token, at least 20 characters

Response content fields:

Field Type Description
valid boolean Always true (failures are returned as error codes)
licenseId number License record ID
productId number Product ID
edition string Current edition ID
expiryTime string/null Expiry time (ISO8601), null = permanent

Notes:

  • Verification results are cached for about 60 seconds; write operations (revoke, unbind, upgrade) invalidate the cache immediately, so there is no delay concern;
  • The software should check expiryTime and stop unlocking features after expiry.

Error codes for this API: tokenInvalid, machineNotActivated, invalidOrRevoked, expired, tooManyAttempts.

5.5 Unbind a Device (before switching machines, login required)

When to call: the user unbinds the old device in "Profile Center → My Licenses", then activates on the new device via 5.3.

POST /license/deactivate

Request parameters (JSON body):

Parameter Type Required Source Description
licenseCode string Yes User license list License code, at least 10 characters
machineCode string Yes User license list The machine code to unbind, at least 8 characters

Response content: true.

Notes:

  • Only the owner of the license (the buyer, or the user who registered the bound machine code) can operate;
  • Unbind quota: by default the same license can be unbound only once within 30 days (configurable in the admin console); exceeding it returns unbindQuotaExceeded.

Error codes for this API: noPermission, machineNotBound, unbindQuotaExceeded.

6. Error Codes

Business errors use a unified response (tip carries a human-readable message):

{
  "code": "BUSINESS_WARNING",
  "requestId": "xxx",
  "success": false,
  "errorMessage": "LICENSE_GENERATE_FAILED",
  "tip": "Signature verification failed"
}

Parameter validation failures return code: "PARAM_VALIDATE_FAILED" and the specific field message in tip.

Error code Meaning
productNotEnabled The product does not have license activation enabled
apiSecretMissing The product has no Software API secret (licenseApiSecret) configured
signatureInvalid Signature verification failed (wrong secret, wrong payload order, or timestamp out of window)
machineCodeInvalid Invalid machine code (shorter than 8 characters)
orderAlreadyUsed This order already generated a license code (idempotency conflict: replayed with a different machine code)
codeNotFound License code not found
revoked License code has been revoked or is unusable
expired License code has expired
invalidOrRevoked License is invalid or revoked during verification
machineNotActivated This machine is not activated
tokenInvalid Invalid activation token
machineLimit The license has reached the maximum number of bound machines
machineNotBound This machine is not bound
noPermission No permission to operate on this license
unbindQuotaExceeded The license can be unbound only once within 30 days; try again later
tooManyAttempts Too many attempts; try again later
productNotFound Product not found
editionRequired Please select the target edition

7. Typical Flows

  1. In-software payment loop: payment succeeds → software/generate (returns the license code + activation token) → the software stores them → call verify on every startup → unlock features; renewal / upgrade → software/upgrade;
  2. Self-service / admin issuance: a license code is generated in the Developer Center or the admin console → the user gets the code → activate in the client to bind the device and get the activation token → verify on startup;
  3. Switching machines: unbind the old device via deactivate in the Profile Center → activate on the new device → verify;
  4. Upgrade strategy difference: SAME_CODE keeps the same code; NEW_CODE issues a new code (the old code is revoked and machine bindings are migrated automatically).

8. Notes

  • Keep the secret server-side only: signing must be done on your software server; if the client gets the secret, the license system is compromised;
  • Machine code stability: use a stable machine fingerprint and hash it; if the machine code changes after reinstalling the OS, unbind first, then activate again;
  • Idempotency: make clientOrderId globally unique (e.g. timestamp + random), repeated requests will not issue duplicate codes;
  • Cache: verify results are cached for about 60 seconds and invalidated immediately by write operations;
  • Rate limiting: failed activations / verifications are rate-limited; the client should show proper error messages and retry with delays;
  • Trust the platform response: validity, edition, and machine limits are decided by the platform; do not relax them on the software side.