1. Activate
Bind the key to a machine and receive a signed offline lease.
Public API
Issue keys in the admin desk, then call these endpoints from your software to activate seats, validate licenses, and free machines.
BASE https://license.strimivo.co.uk/api/v1
JSON Content-Type: application/json
Every licensed install needs a license key, a product slug (from Admin → Products), and a stable machine_id for that device.
Bind the key to a machine and receive a signed offline lease.
On each launch (or heartbeat), confirm the seat is still allowed.
Free a seat when the user uninstalls or moves devices.
| Field | Required | Description |
|---|---|---|
license_key |
Yes | Key like STRM-XXXXX-XXXXX-XXXXX-XXXXX |
product |
Yes | Product slug from admin (e.g. strimivo) |
machine_id |
Activate / deactivate / usually validate | Stable unique ID for this install. Changing it consumes a new seat. |
machine_name |
No | Human label (hostname) |
app_version |
No | Your app version string |
The public license API does not use API keys or admin logins. Clients send the customer’s license key in the JSON body.
Never call /api/admin/* from shipped software. Admin routes are cookie-session
only for humans at /admin/.
/api/v1/health
Service health check. No body required.
{
"ok": true,
"service": "strimivo-license",
"runtime": "php",
"lease_hours": 72,
"public_url": "https://license.strimivo.co.uk",
"time": "2026-11-15T17:00:00.000Z"
}
/api/v1/public-key
Public material to verify signed offline leases (Ed25519 when available).
/api/v1/activate
Bind a license to this machine. Safe to call again on the same machine (idempotent).
{
"license_key": "STRM-XXXXX-XXXXX-XXXXX-XXXXX",
"machine_id": "unique-stable-device-id",
"machine_name": "STEPHEN-PC",
"app_version": "1.0.0",
"product": "strimivo"
}
{
"ok": true,
"valid": true,
"message": "License activated.",
"license": {
"id": "...",
"key_tail": "XXXXX",
"product": "strimivo",
"product_name": "Strimivo",
"status": "active",
"type": "perpetual",
"features": {},
"expires_at": null,
"seats_used": 1,
"seats_max": 1
},
"activation": {
"id": "...",
"machine_id": "unique-stable-device-id",
"machine_name": "STEPHEN-PC"
},
"lease": {
"token": "v1....",
"expires_at": "2026-11-18T17:00:00.000Z",
"offline_ok": true
}
}
/api/v1/validate
Check that the license is still allowed. If the product uses seat limits
(seats_max > 0), this machine must already be activated.
{
"license_key": "STRM-XXXXX-XXXXX-XXXXX-XXXXX",
"machine_id": "unique-stable-device-id",
"product": "strimivo",
"app_version": "1.0.0"
}
Success shape matches activate (valid: true + refreshed lease).
/api/v1/heartbeat
Same body and behaviour as validate. Call periodically while the app is open.
/api/v1/deactivate
Release this machine’s seat so another device can activate.
{
"license_key": "STRM-XXXXX-XXXXX-XXXXX-XXXXX",
"machine_id": "unique-stable-device-id",
"product": "strimivo"
}
{
"ok": true,
"valid": false,
"deactivated": true,
"message": "Machine deactivated.",
"license": { "...": "..." }
}
Failures return JSON with ok: false and usually valid: false.
{
"ok": false,
"valid": false,
"error": "seat_limit",
"message": "All seats are in use (1 of 1). ..."
}
error | Meaning | What to show the user |
|---|---|---|
invalid_request | Missing/bad fields | Fix the key / required fields |
machine_required | Need machine_id | App bug — generate machine id |
license_not_found | Unknown key | Invalid license key |
license_revoked | Admin revoked | Contact support |
license_suspended | Temporarily blocked | Contact support |
license_expired | Past expiry | Renew license |
product_mismatch | Wrong product slug | Key is for another product |
seat_limit | No free seats | Deactivate another PC |
not_activated | Validate before activate | Call activate first |
machine_id on first install.POST /activate.valid: true, unlock the app and store the key + lease.POST /validate (or trust lease until lease.expires_at offline).POST /heartbeat every few hours.POST /deactivate.
Online checks see revoke/suspend immediately. An offline lease can keep working until
lease.expires_at (default 72 hours).
curl -s -X POST https://license.strimivo.co.uk/api/v1/activate \
-H "Content-Type: application/json" \
-d '{
"license_key": "STRM-XXXXX-XXXXX-XXXXX-XXXXX",
"machine_id": "dev-1",
"product": "strimivo",
"app_version": "1.0.0"
}'
const BASE = "https://license.strimivo.co.uk/api/v1";
async function activate(key, machineId, product = "strimivo") {
const res = await fetch(`${BASE}/activate`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
license_key: key,
machine_id: machineId,
product,
app_version: "1.0.0",
}),
});
return res.json(); // check result.valid
}
Integrate online licensing using this docs page and:
https://license.strimivo.co.uk/docs/INTEGRATION.md
Base API: https://license.strimivo.co.uk/api/v1
Product slug: strimivo
Implement: stable machine_id, activate on first use, validate on launch,
heartbeat while running, deactivate in settings. Handle every error code.
Never call /api/admin from the shipped app.