Use this catalog to recognize notifications that KDPika Licensing actually emits.
What you will learn
- Identify the trigger and fields for every event.
- Separate notifications from authoritative license validation.
- Handle known gaps without inventing additional event types.
Prerequisites
- Complete endpoint setup.
- Implement signature verification.
- Read license lifecycle rules.
Envelope shared by every event
| Field | Type | Meaning |
|---|---|---|
| id | string | Event ID beginning evt_; not a UUID contract. Stable across delivery retries. |
| event | string | Name from this catalog. |
| created_at | string | UTC ISO 8601 notification-creation time, not the delivery attempt time. |
| environment | string | sandbox or live; pin the expected value in your receiver. |
| data | object | Event-specific fields described below. |
The payloads below were captured from real local Sandbox service and maintenance operations on 2026-10-14. All identifiers and values are synthetic. They were queued locally, not delivered by a third-party service. Formatting here is for readability; verify the original incoming HTTP bytes, not this displayed JSON formatting.
Only subscribed active endpoints in the same organization and environment receive ordinary events. A product-scoped endpoint receives its product; an All products endpoint receives eligible events across that environment. The envelope does not include an organization ID or product ID: your endpoint configuration and your saved license mapping establish that context. Do not assume resource ownership from a supplied license ID alone.
license.created
A successful license creation commits, then queues this notification. It contains a masked key, never the complete key.
{
"id": "evt_6db5fc08a2fdc0664fd58904",
"data": {
"license": {
"id": "lic_18d0daa92fddced51a44ed14",
"status": "active",
"expires_at": "2026-11-13T17:43:50+00:00",
"license_key_mask": "TESTDOCS-••••-••••-7CCL"
}
},
"event": "license.created",
"created_at": "2026-10-14T17:43:50+00:00",
"environment": "sandbox"
}
| Field inside data | Type | Meaning |
|---|---|---|
license.id | string | Created license ID. |
license.status | string | active at creation. |
license.expires_at | string or null | UTC expiration or null for an unbounded license. |
license.license_key_mask | string | Display-only key mask; cannot activate a license. |
Recommended action: Record the license ID in your server-side order mapping. Do not issue another license or attempt to email the mask as a key.
license.activated
A successful activation, including a new activation token for an existing installation, queues this notification.
{
"id": "evt_c8213ce9e0751fcbb2079e82",
"data": {
"device": {
"id": "dev_af3087ec2eeb536a4f4c61a7"
},
"license": {
"id": "lic_18d0daa92fddced51a44ed14",
"status": "active"
}
},
"event": "license.activated",
"created_at": "2026-10-14T17:43:50+00:00",
"environment": "sandbox"
}
| Field inside data | Type | Meaning |
|---|---|---|
license.id | string | Activated license ID. |
license.status | string | active at activation. |
device.id | string | Server device-record ID, not the installation ID you supplied. |
Recommended action: Update installation activity in your backend. Authorize application features using the validated signed response, not this notification.
license.deactivated
Client deactivation or a device release from the customer portal queues this notification. Deactivating a device from the developer Devices screen does not emit this event.
{
"id": "evt_47da0040c780d987b4662467",
"data": {
"device": {
"id": "dev_af3087ec2eeb536a4f4c61a7"
},
"license": {
"id": "lic_18d0daa92fddced51a44ed14"
}
},
"event": "license.deactivated",
"created_at": "2026-10-14T17:43:50+00:00",
"environment": "sandbox"
}
| Field inside data | Type | Meaning |
|---|---|---|
license.id | string | Affected license ID. |
device.id | string | Released server device ID. |
source | string, optional | customer_portal for the portal release path; absent on client deactivation. |
Recommended action: Update your device activity view. Do not infer that every possible device change generates this notification.
license.suspended
An allowed suspension queues this event. Repeating suspension can create a new event even when the license was already suspended.
{
"id": "evt_863acadaee69a2a86662efc1",
"data": {
"reason": "",
"license": {
"id": "lic_18d0daa92fddced51a44ed14",
"status": "suspended"
}
},
"event": "license.suspended",
"created_at": "2026-10-14T17:43:50+00:00",
"environment": "sandbox"
}
| Field inside data | Type | Meaning |
|---|---|---|
license.id | string | Affected license ID. |
license.status | string | suspended. |
reason | string or null | Operation reason; can be an empty string. |
Recommended action: Notify your support workflow and refresh your backend license view. Do not run another suspension in response to the same notification.
license.restored
The suspended-to-active transition queues this event. Setting an already active license to active does not produce license.restored.
{
"id": "evt_0f5d4d8a4ee2ab283d1822bc",
"data": {
"reason": "",
"license": {
"id": "lic_18d0daa92fddced51a44ed14",
"status": "active"
}
},
"event": "license.restored",
"created_at": "2026-10-14T17:43:50+00:00",
"environment": "sandbox"
}
| Field inside data | Type | Meaning |
|---|---|---|
license.id | string | Restored license ID. |
license.status | string | active. |
reason | string or null | Operation reason; can be an empty string. |
Recommended action: Refresh current license state. Previously revoked activation tokens do not become usable merely because restoration was reported; the application may need to activate again.
license.revoked
An allowed revocation queues this event. Repeating revocation can create another event ID.
{
"id": "evt_0d29f4ae752612f98e63f18e",
"data": {
"reason": "Synthetic test",
"license": {
"id": "lic_18d0daa92fddced51a44ed14",
"status": "revoked"
}
},
"event": "license.revoked",
"created_at": "2026-10-14T17:43:50+00:00",
"environment": "sandbox"
}
| Field inside data | Type | Meaning |
|---|---|---|
license.id | string | Revoked license ID. |
license.status | string | revoked. |
reason | string or null | Operation reason; can be an empty string. |
Recommended action: Flag the order/license mapping for support. Revocation is terminal in the current lifecycle; do not promise automatic restoration after a reversed refund or won dispute.
license.renewed
A successful renewal queues this event. The API adds days to a future expiration, or to the current time if the expiration has passed or is absent.
{
"id": "evt_25995883974e153db0cf8860",
"data": {
"days": 365,
"license": {
"id": "lic_18d0daa92fddced51a44ed14",
"status": "active",
"expires_at": "2027-11-13T17:43:50+00:00"
}
},
"event": "license.renewed",
"created_at": "2026-10-14T17:43:50+00:00",
"environment": "sandbox"
}
| Field inside data | Type | Meaning |
|---|---|---|
license.id | string | Renewed license ID. |
license.status | string | State after renewal; a suspended license stays suspended. |
license.expires_at | string | New UTC expiration. |
days | integer | Days added, from 1 through 3650 inclusive. |
Recommended action: Record the resulting expiration and reconcile it with your store ledger. Never call renew again merely because this notification is delivered twice.
license.expiring
A maintenance run selects active licenses due within seven days and emits reminders when the remaining rounded-up whole days equal seven or one. The reminder marker is license ID plus day count, not expiration revision.
{
"id": "evt_c237ff96e67f2e36ecb4f0ad",
"data": {
"license": {
"id": "lic_f8f3017881fdbc8307163c79",
"expires_at": "2026-10-15T17:46:36+00:00",
"days_remaining": 1
}
},
"event": "license.expiring",
"created_at": "2026-10-14T17:46:36+00:00",
"environment": "sandbox"
}
| Field inside data | Type | Meaning |
|---|---|---|
license.id | string | License approaching expiration. |
license.expires_at | string | UTC expiration. |
license.days_remaining | integer | Rounded-up reminder bucket: 7 or 1. |
Recommended action: Schedule a customer reminder with your own deduplication and consent policy. After renewal the same reminder bucket can be suppressed by the existing marker; reconcile scheduled communications independently.
license.expired
A maintenance run persists an elapsed active or suspended license as expired and expires its active activation tokens. A rejected API validation by itself does not guarantee this event or the stored state transition.
{
"id": "evt_4c8cbd02e77bfc62c54484c4",
"data": {
"license": {
"id": "lic_f8f3017881fdbc8307163c79",
"status": "expired"
}
},
"event": "license.expired",
"created_at": "2026-10-14T17:46:36+00:00",
"environment": "sandbox"
}
| Field inside data | Type | Meaning |
|---|---|---|
license.id | string | Expired license ID. |
license.status | string | expired. |
Recommended action: Refresh the license view and offer your own renewal route if supported. A delayed notification does not extend paid access or SDK offline grace.
device.reset
A developer resets all active devices for a license. Active device rows are deactivated and active activation tokens are revoked.
{
"id": "evt_eb4ce6fbdcc85b9e5384e935",
"data": {
"license": {
"id": "lic_18d0daa92fddced51a44ed14"
}
},
"event": "device.reset",
"created_at": "2026-10-14T17:43:50+00:00",
"environment": "sandbox"
}
| Field inside data | Type | Meaning |
|---|---|---|
license.id | string | License whose devices were reset. |
Recommended action: Tell your application/support workflow that reactivation may be required. This event does not contain a complete device list.
test.ping
Send test queues a synthetic notification for the selected endpoint even if test.ping is not in its business-event subscription. A disabled endpoint can queue it but does not send it until enabled.
{
"id": "evt_ffa11b785e0ede73d9e69801",
"data": {
"message": "Signed webhook test",
"webhook_id": "whk_2bf9c0559190a2101b3b9d1b"
},
"event": "test.ping",
"created_at": "2026-10-14T17:46:36+00:00",
"environment": "sandbox"
}
| Field inside data | Type | Meaning |
|---|---|---|
message | string | Signed webhook test. |
webhook_id | string | Selected endpoint ID. |
Recommended action: Confirm signature verification and durable receipt only. Do not issue, renew or unlock a license.
Events that do not exist
There is no license.validated, plan.changed, customer.created, email.delivered or store-payment event in this outbound contract. Device deactivation from the developer Devices screen does not emit license.deactivated. A recurring-payment integration receives payment-provider events on your backend, calls the appropriate licensing API, then may receive the corresponding licensing notification. Do not create an event feedback loop.
Expected result
Every recognized event has an authenticated envelope, an explicit handler and a durable event-ID deduplication record. Unrecognized names are rejected or quarantined without a business action.
Common mistakes
- Treating a license key mask as a usable key.
- Assuming all events include customer email, plan, product or a full license object.
- Extending a license again when license.renewed is redelivered.
- Assuming a reminder or expiration notification arrives at an exact wall-clock instant.
Security notes
Event data can be delayed or arrive out of order. Use get license on your authenticated backend when you need current resource details. Client feature access still requires a valid, verified signed activation/validation response. Treat reason text as untrusted display content and escape it in HTML, notifications and logs.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| No customer email in license.created | The contract only sends a key mask and license fields | Use your secured order/customer mapping; do not scrape logs for a key |
| No reminder after a later renewal | Reminder deduplication is not keyed by expiration revision | Reconcile reminders from your own billing schedule |
| No expiry event after rejected validation | Maintenance performs the persistent transition | Check signed/API validity now; do not wait for a notification |
| Several activation events for one installation | Reactivation can rotate a token | Track server device ID and do not count events as new seats |
Next steps
Implement the delivery and duplicate-handling rules, then run the local receiver test.