Webhook events
Every event Licet delivers to your webhook endpoints, and what its
data.object carries. How to receive and verify them is covered in
Handling webhooks.
All events share the same envelope:
{
"id": "evt_01J…",
"type": "licence.created",
"api_version": "2026-06-01",
"created_at": "2026-07-14T12:00:00Z",
"sequence": 1024,
"account_id": "acct_…",
"application_id": "app_…",
"data": { "object": { … } },
"previous": null
}
Payloads are thin — identifiers and status, never customer data. Fetch the
full entity with the API when you need more
(GET /v1/licences/{licence_id} with a read-scoped key).
Licence lifecycle
| Event | Fires when | data.object |
|---|---|---|
licence.created | A payment (Checkout or sale event) provisions a licence for a new customer reference | licence_id, plan_id, status |
licence.plan_changed | A payment lands for a customer who already holds a licence — upgrade/repeat purchase. previous carries { "plan_id": … } | licence_id, plan_id, status |
licence.suspended | Manual suspend; a plan is archived (payload adds reason: "plan_archived"); repeated subscription payment failures; some refund flows | licence_id, plus status / reason when applicable |
licence.reactivated | Manual reactivate of a suspended licence | licence_id, status |
licence.revoked | Manual revoke, or a full refund / chargeback | licence_id, status |
licence.expired | A licence passes its expires_on (background sweep), or its subscription is cancelled | licence_id, status |
licence.retired | Manual retire | licence_id, status |
Payments and money
| Event | Fires when | data.object |
|---|---|---|
payment.succeeded | An integrated checkout completes and the licence is provisioned | licence_id, amount, currency |
payment.provision_failed | The customer paid but no licence could be issued (e.g. the plan was archived mid-checkout). Act on this — someone has paid for something they haven't received. The session stays open, so a replay provisions once the cause is fixed. | session_id, plan_id, amount, currency, reason |
refund.processed | A Stripe refund or dispute is handled — accompanied by the licence event it caused (revoked on full, downgraded on partial) | licence_id, charge_ref, amount, lane |
spend_cap.reached | Your monthly transaction-fee budget is spent; new fee-incurring checkouts pause until the period resets or the cap is raised. Once per period. | period, cap_minor, spent_minor |
Diagnostics
| Event | Fires when | data.object |
|---|---|---|
webhook.test | You press Send test event on the deliveries page | ping: true |
Notes for consumers
- Delivery is at-least-once — dedupe on the envelope
id. - Order isn't guaranteed — reconcile with
sequenceor by re-fetching the entity rather than assuming arrival order. - The catalogue will grow. Unknown event types should be acknowledged with a
2xx and ignored, not treated as errors — especially if you subscribed with
"*".