MediaGrabber Pro

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:

export const pluginConfig = {
  // ...
  webhookUrl: process.env.PLUGIN_WEBHOOK_URL ?? '',
}

Event types

EventFires when
license.activatedA new site/device activates a license
license.deactivatedA site/device is removed
license.expiredA license expires (subscription lapse / trial end)
subscription.renewedA billing period renews
subscription.canceledCancellation is scheduled
usage.limit_reachedA metered counter hits the plan limit

Payload shape

{
  event: 'license.activated',
  licenseId: 'lic_abc123',
  userId: 'usr_def456',
  timestamp: '2025-06-01T12:00:00Z',
  data: {
    domain: 'acmecorp.com',
    fingerprint: 'abc...',
    // event-specific fields
  }
}

Verify the signature

Every event is signed with HMAC-SHA256 in the X-Webhook-Signature header. Always verify before acting, using the shared secret:

import { createHmac } from 'node:crypto'
 
function verifyWebhook(body: string, signature: string, secret: string): boolean {
  const expected = createHmac('sha256', secret).update(body).digest('hex')
  return signature === `sha256=${expected}`
}

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.

On this page

Plugin Webhooks | MediaGrabber Pro