Skip to content

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

{ "status": "seat_full", "message": "All seats are in use" }

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

{ "license_key": "XXXX-XXXX-XXXX", "fingerprint": "sha256-of-hardware-id" }

Response

{ "status": "deactivated" }

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.