← Plugin SDK

POST /api/v1/license/heartbeat

Refresh the lastSeenAt timestamp for an already-activated machine. Cheap, idempotent.

POST /api/v1/license/heartbeat

Call this once per Unity Editor session — or once a day, whichever cadence the plugin prefers — so the dashboard shows accurate activity data and we can later auto-expire abandoned activations.

The endpoint is idempotent within a 5-minute window: a repeat call inside that window returns 200 { ok: true, skipped: true, ts } without a database write. The dashboard "last seen" granularity is therefore 5 minutes.

Request

Headers: see HMAC Signing.

Body (JSON):

{
  "licenseKey": "uuid-v4",     // required
  "machineId":  "8-128 chars"  // required, same value used in /activate
}

Responses

200 OK — heartbeat accepted

Updated:

{ "ok": true, "ts": 1716998400123 }

Skipped (within 5-minute window of previous heartbeat):

{ "ok": true, "skipped": true, "ts": 1716998400123 }

ts is the server-side time in milliseconds since the Unix epoch. Plugins should treat the server clock as authoritative.

400 LICENSE_API_MALFORMED (1702)

Body did not match the schema.

401 LICENSE_API_BAD_SIGNATURE (1700) / STALE_TIMESTAMP (1701)

Signature verification failed. See HMAC Signing.

403 LICENSE_API_REVOKED (1708)

The license has been revoked (chargeback, fraud, manual action). Plugin should treat this as a permanent failure — stop sending heartbeats, lock the feature, surface a support link.

403 LICENSE_API_INACTIVE (1704)

The license exists in some other non-ACTIVE state. Body includes the status field. Treat as a soft failure: poll /status on a longer interval and resume if it returns to ACTIVE.

404 LICENSE_API_NOT_FOUND (1703)

License key unknown or soft-deleted. Permanent failure.

404 LICENSE_API_MACHINE_NOT_ACTIVATED (1709)

The license is valid but this machine has never been activated. Re-run /activate. The heartbeat handler does not auto-activate.

429 LICENSE_API_RATE_LIMITED (1706)

Honour the Retry-After header. Per-license-key budget is 5 calls / 60s — a session that pings more than once per minute is doing it wrong.

Failure recovery

If a heartbeat returns 4xx other than RATE_LIMITED, back off and call /status instead. Status is read-only and gives a cleaner signal about whether the license is still healthy.

Audit log

Heartbeats are not individually logged in the audit table. The endpoint is too high-frequency. Use the dashboard's per-activation lastSeenAt for activity tracking.