Plugin Webhooks
Receive license and subscription events at your own endpoint, and verify their signatures.
Instead of polling, you can have the portal push license events to an endpoint you own. Useful for provisioning, deprovisioning, and analytics.
These are the portal's outbound webhooks to your plugin backend. They are
separate from the inbound billing webhooks the portal receives at
/webhooks/billing.
Register your endpoint
Set the URL the portal should call in packages/config/src/plugin.ts:
Event types
| Event | Fires when |
|---|---|
license.activated | A new site/device activates a license |
license.deactivated | A site/device is removed |
license.expired | A license expires (subscription lapse / trial end) |
subscription.renewed | A billing period renews |
subscription.canceled | Cancellation is scheduled |
usage.limit_reached | A metered counter hits the plan limit |
Payload shape
Verify the signature
Every event is signed with HMAC-SHA256 in the X-Webhook-Signature header.
Always verify before acting, using the shared secret:
Compute the HMAC over the raw request body, before any JSON parsing — even whitespace differences will break the signature.
Handler checklist
Read the raw body
Capture the unparsed body for signature verification.
Verify the signature
Reject with 401 if it doesn't match.
Respond fast, process async
Return 2xx quickly; do slow work in the background so the portal isn't kept
waiting (and doesn't retry).
Be idempotent
The same event may be delivered more than once — key your processing on
licenseId + event + timestamp.