Webhooks
Open an app and choose Webhooks, then Add webhook with a URL and the events you want.
The URL must be public HTTPS. Discord and Slack webhook URLs get a readable message; any other URL gets JSON.
Events
Section titled “Events”| Event | When |
|---|---|
user.register |
A password account was created |
user.login |
A password sign-in succeeded |
user.login_failed |
A password sign-in failed |
license.login |
A key sign-in succeeded |
license.redeemed |
A key was added to an account |
license.created |
Keys were generated (panel, API, store) |
license.revoked / license.unrevoked |
A key was revoked or restored |
license.deleted |
A key was deleted |
user.banned / user.unbanned |
A user was banned or unbanned |
user.deleted |
A user was deleted |
user.renamed |
A username changed |
user.paused |
A user was paused |
hwid.reset |
A PC lock was reset |
What your server receives
Section titled “What your server receives”POST /your/endpoint HTTP/1.1Content-Type: application/jsonUser-Agent: licensing-api-webhooks/1X-Webhook-Timestamp: 1794497606X-Webhook-Signature: sha256=5b1f…
{"event":"license.created","app":"My App","timestamp":1794497606,"data":{"batch_id":"bat_…","quantity":2,"preset":"month","tier":"Default"}}Deliveries time out after 5 seconds and are not retried.
Checking the signature
Section titled “Checking the signature”When you add a webhook, the panel shows its signing secret once (base64). The signature is
HMAC-SHA256 over timestamp + "." + raw body, keyed with the decoded secret, in hex:
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody, timestamp, header, secretBase64) { if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false; // reject old deliveries const expected = "sha256=" + createHmac("sha256", Buffer.from(secretBase64, "base64")) .update(`${timestamp}.${rawBody}`) .digest("hex"); return expected.length === header.length && timingSafeEqual(Buffer.from(expected), Buffer.from(header));}Always check it against the raw body, before parsing the JSON.
Own webhooks
Section titled “Own webhooks”A manager with Webhooks: Own can add webhooks in any app they can reach. Those webhooks are told only about keys that manager generated and the users who redeemed them; bulk actions send them just their part. The owner sees every webhook, who added it and what it hears.
Such a webhook goes quiet as soon as its creator is disabled, loses the permission or loses the app, and it is deleted with them.