Webhooks
SoftLicense POSTs a JSON event to your endpoint when licenses, activations or customers change. Add endpoints under Developers → Webhooks, or with POST /api/v1/webhooks.
Payload
POST https://your-app.example.com/softlicense
SoftLicense-Signature: t=1719000000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
SoftLicense-Event-Id: whe_…
SoftLicense-Event-Type: license.revoked
{ "id": "whe_…", "type": "license.revoked", "created_at": "…", "organization_id": "…",
"data": { "license": { "id": "lic_…", "key": "ACME-…", "status": "revoked", ... }, "reason": "chargeback" } }Verifying signatures
Compute HMAC-SHA256(secret, t + "." + rawBody) and compare it to v1 with a constant-time comparison. Reject if t is more than five minutes old. Use the raw request body, not a re-serialised one.
import { createHmac, timingSafeEqual } from "node:crypto";
const [t, v1] = header.split(",").map((kv) => kv.split("=")[1]);
const expected = createHmac("sha256", SECRET).update(`${t}.${rawBody}`).digest("hex");
if (!timingSafeEqual(Buffer.from(expected), Buffer.from(v1))) throw new Error("bad signature");Delivery and retries
- Respond with any 2xx within 10 seconds. Anything else is retried with backoff: 1m, 5m, 30m, 2h, 12h, then 24h, up to 10 attempts.
- Endpoints that fail continuously for 7 days are disabled and your team is emailed. Re-enable from the dashboard; failed deliveries can be retried individually.
- Deliveries are at-least-once. Use
SoftLicense-Event-Idto de-duplicate. - Endpoints must be public
httpsURLs; private and internal addresses are rejected.
Events
| Type | When |
|---|---|
license.created | A license was issued |
license.updated | License details, expiry or entitlements changed |
license.renewed | A license was renewed or extended |
license.suspended | A license was suspended |
license.reinstated | A suspended license was reinstated |
license.revoked | A license was revoked |
license.expired | A license passed its expiry date |
license.expiring_soon | A license will expire within the configured notice window |
activation.created | A machine activated a license |
activation.deleted | A machine was deactivated |
activation.lease_expired | A floating lease or heartbeat lapsed and the seat was freed |
customer.created | A customer record was created |
customer.updated | A customer record was updated |