Activate, validate & deactivate¶
All endpoints: POST, JSON body, header Content-Type: application/json, and
X-Berlanggan-Secret if the product requires it. Always return HTTP 200.
POST /v1/activate¶
Register one device and issue an activation token.
Request
{
"license_key": "XXXX-XXXX-XXXX",
"fingerprint": "sha256-of-hardware-id",
"machine_name": "DESKTOP-01"
}
fingerprint— a stable per-device hash you compute yourself (e.g. SHA-256 of machine-id + disk serial). Must be consistent across calls.machine_name— optional, shown in the user's dashboard.
Response — success
{
"status": "active",
"token": "<signed token>",
"expires_at": "2026-07-01T00:00:00Z",
"token_expires_at": "2026-07-01T00:00:00Z",
"license_expires_at": "2027-06-01T00:00:00Z",
"grace_days": 3,
"entitlements": { "MAX_AGENTS": 10, "WHATSAPP": true },
"entitlement": { "license_id": "…", "fingerprint": "…", "product_id": "…", "status": "active", "entitlements": { "MAX_AGENTS": 10 } },
"entitlement_signature": "base64-ed25519"
}
Response — failure
Store token locally (encrypted if possible). Treat a response with an empty
entitlement_signature as untrusted if your build has a public key — see
Verifying the entitlement signature.
POST /v1/validate (heartbeat)¶
A periodic check. Validates the token and returns a fresh, extended one.
Request
{
"license_key": "XXXX-XXXX-XXXX",
"fingerprint": "sha256-of-hardware-id",
"token": "<last token>"
}
Response — same shape as activate. Always replace your local token with
the latest token from the response.
If status is not active/grace, apply the restrictions from the status
table in the Overview. If the request fails due to the
network, don't lock immediately — honour grace_days (see
Heartbeat & offline grace).
POST /v1/deactivate¶
Release this device's seat (e.g. on uninstall or changing computers).
Request
Response
After this the seat is free for another device. The local token is no longer valid.
POST /v1/operation-authorize¶
Request a short-lived grant for a premium operation configured by the publisher (e.g. bulk export, a metered feature).
Request
{
"license_key": "XXXX-XXXX-XXXX",
"fingerprint": "sha256-of-hardware-id",
"token": "<active token>",
"operation": "bulk_export",
"request_hash": "optional-sha256-payload"
}
Response
{
"status": "authorized",
"authorization": { "operation": "bulk_export", "expires_at": "…" },
"authorization_signature": "base64-ed25519"
}
Verify authorization_signature the same way as entitlement_signature.
Rate limiting¶
Limited per key and per IP. When limited, status = rate_limited — use
exponential backoff. A reasonable heartbeat (daily to every few hours) won't be
limited.