Webhook events
MonetizeIt delivers events to your HTTPS endpoints so your billing, CRM and automation stay in sync without polling. The contract follows two open standards: the payload is a CloudEvents 1.0 envelope, and delivery is signed per Standard Webhooks.
Subscribing
Section titled “Subscribing”Create a subscription from the portal’s Webhooks page or the admin API:
POST /api/v1/webhooks/admin/subscriptions— register an endpoint URL, the event types you want, an optional filter, and a signing secret.GET /api/v1/webhooks/admin/subscriptions·GET | PATCH | DELETE …/{id}— manage them.POST …/{id}/test-fire— send a sample event to your endpoint.
Every event type the platform emits is discoverable, unauthenticated, at
GET /api/v1/webhooks/schemas.
Patterns and filters
Section titled “Patterns and filters”A subscription matches event types exactly (Entitlement.Activated), by prefix
wildcard (Entitlement.*), or all (*). You can narrow further by entity kind
(entitlement, monitored-asset, …), by severity (for overage events), and
by attribute equality.
Registration challenge
Section titled “Registration challenge”When you create a subscription, MonetizeIt immediately POSTs a
Webhooks.Registration.Challenge to your URL. Respond 2xx with a JSON body
echoing the challenge — {"challenge": "<data.challenge>"} — and a
webhook-signature response header signed with your shared secret over
{webhook-id}.{webhook-timestamp}.{your response body}. The subscription becomes
Active only once both check out — this proves you own the endpoint and hold
the secret. Subscriptions move through PendingVerification → Active, and can
later be Disabled or Suspended. The receiving side, with code, is in
Receiving webhooks.
The envelope
Section titled “The envelope”Every delivery is a CloudEvents 1.0 JSON document:
{ "specversion": "1.0", "id": "01J…", "source": "urn:monetizeit:…", "type": "Entitlement.Activated", "time": "2026-06-16T10:00:00Z", "subject": "…", "datacontenttype": "application/json", "entitykind": "entitlement", "entityid": "…", "eventversion": 1, "data": { }}data is event-specific and non-strict — ignore fields you don’t recognise, so
new ones never break you. Test deliveries (sent from the portal or the test-fire
endpoint) carry "_test": true in data; gate on it so test events never touch
real state.
Verifying a delivery
Section titled “Verifying a delivery”Each request carries the Standard Webhooks headers:
| Header | Meaning |
|---|---|
webhook-id | The envelope id |
webhook-timestamp | RFC 3339 UTC send time |
webhook-signature | v1, + base64 HMAC-SHA256 |
webhook-event-type | e.g. Entitlement.Activated |
webhook-delivery-attempt | Retry counter |
webhook-callback-token | Optional short-lived JWT (see below) |
Recompute the signature over {webhook-id}.{webhook-timestamp}.{raw-body} and
compare in constant time:
signature = "v1," + base64( HMAC_SHA256(secret, id + "." + timestamp + "." + body) )Reject anything that doesn’t match, or whose timestamp is too old to trust.
Secret rotation
Section titled “Secret rotation”During a rotation there is an overlap window: MonetizeIt sends both signatures,
space-separated, in webhook-signature. Accept the delivery if either verifies,
so you can roll keys with no dropped events.
Calling back
Section titled “Calling back”If your subscription requests callback scopes, each delivery includes a short-lived
JWT in webhook-callback-token. Use it as a bearer token to call straight back into
the admin API with exactly those scopes — no separate OAuth round-trip. Only
read / create / update / write verbs are allowed; delete and wildcards are not.
Delivery and retries
Section titled “Delivery and retries”Delivery is at-least-once and idempotent — deduplicate on webhook-id. Failed
deliveries (5xx, timeout, DNS) retry with exponential backoff; once retries are
exhausted the delivery is recorded as failed and kept for inspection, and every
attempt is audited.
Event catalog
Section titled “Event catalog”| Event type | Fires when |
|---|---|
Entitlement.Activated | A license is activated |
Entitlement.Expiring | An entitlement is approaching expiry |
Entitlement.TrialExpiring | A trial is approaching its end |
Entitlement.Renewed | A subscription period renews |
Entitlement.Cancelled | An entitlement is cancelled |
Entitlement.PlanApplied | A plan is applied or changed |
MeteredUsage.OverageStatusChanged | A monitored asset crosses a quota tier (Normal / Warning / Critical / OverUsage) |
CreditBalance.StatusChanged | A prepaid credit balance crosses a threshold — e.g. running low or depleted — so you can prompt a top-up before work is blocked |
DataSubjectRequest.Filed · .Approved · .Rejected · .Completed | A data-subject request changes state |
User.Erased | A user is erased |
Webhooks.Registration.Challenge | Sent once, to verify a new subscription |