Webhooks & Events
Configure HTTPS endpoints to receive real-time notifications when licensing, device, product, or customer events occur.
Keymint supports outbound webhooks, allowing your systems to receive real-time POST payloads when licensing and database events occur. Expiration is evaluated during license operations; there is no separate license.expired webhook event. The dashboard's Deliveries view is limited to actual outbound delivery attempts; an internal event is not shown there unless it matched an enabled endpoint and was attempted.
Delivery Architecture
Whenever an action occurs, Keymint inserts a webhook event and schedules deliveries to all matching enabled endpoints:
Event Types
You can subscribe your endpoints to specific events from this catalog:
| Domain | Event | Trigger |
|---|---|---|
| Licensing | license.created | License key generated via dashboard or REST API |
license.updated | License key fields modified | |
license.enabled | License activated/unblocked | |
license.disabled | License deactivated/blocked | |
license.deleted | License key deleted | |
license.activations_reset | Activation count reset | |
license.offline_signed | Offline license file signed | |
| Devices | device.activated | REST API activation succeeds |
device.deactivated | REST API deactivation succeeds | |
| Floating | floating_session.checked_out | Floating seat checkout or extension |
floating_session.checked_in | Floating seat checkin | |
floating_session.revoked | Vendor force-revokes floating session | |
floating_session.limit_hit | Checkout rejected (concurrent limit) | |
| Products | product.created | Product created |
product.updated | Product updated or toggled | |
product.deleted | Product deleted | |
| Customers | customer.created | Customer created |
customer.updated | Customer updated | |
customer.disabled | Customer deactivated | |
customer.enabled | Customer reactivated | |
customer.deleted | Customer deleted |
Signature Verification
Each webhook delivery includes an HMAC-SHA256 signature calculated over the request body and a timestamp. Your server should verify the signature before processing payloads to guarantee authenticity and prevent replay attacks.
Headers Sent
Keymint-Event-Id— Unique event identifierKeymint-Delivery-Id— Unique delivery attempt identifierKeymint-Event-Type— Event type stringKeymint-Timestamp— Unix timestamp (seconds)Keymint-Signature—t=<timestamp>,v1=<hex_hmac>
Verification Steps
- Parse the timestamp
tand signaturev1from theKeymint-Signatureheader. - Verify the timestamp is fresh (e.g. within 5 minutes) to defend against replay attacks.
- Concatenate the timestamp and raw body payload separated by a dot:
signed_payload = timestamp + "." + raw_request_body - Calculate the HMAC-SHA256 signature using your endpoint's signing secret.
- Use a timing-safe comparison to verify the computed hash matches the received
v1signature.
Example Verification (Node.js)
const crypto = require('crypto');
function verifyWebhook(headers, rawBody, endpointSecret) {
const signatureHeader = headers['keymint-signature'];
if (!signatureHeader) throw new Error('Missing signature header');
const parts = signatureHeader.split(',');
const timestamp = parts.find(p => p.startsWith('t='))?.substring(2);
const receivedSig = parts.find(p => p.startsWith('v1='))?.substring(3);
if (!timestamp || !receivedSig) throw new Error('Malformed signature header');
// Replay protection (5 minutes tolerance)
const diff = Math.abs(Math.floor(Date.now() / 1000) - parseInt(timestamp, 10));
if (diff > 300) throw new Error('Signature expired');
// Compute signature
const signableContent = timestamp + '.' + rawBody;
const expectedSig = crypto
.createHmac('sha256', endpointSecret)
.update(signableContent)
.digest('hex');
// Timing safe comparison
const bufferExpected = Buffer.from(expectedSig, 'utf8');
const bufferReceived = Buffer.from(receivedSig, 'utf8');
if (bufferExpected.length !== bufferReceived.length ||
!crypto.timingSafeEqual(bufferExpected, bufferReceived)) {
throw new Error('Invalid signature');
}
return true;
}Security & Reliability Controls
- SSRF Prevention: Keymint blocks private, loopback, link-local, and metadata IPs during destination DNS resolution.
- Payload Sanitization: Critical secrets (such as raw passwords, tokens, API keys, and session keys) are redacted with
[REDACTED]before leaving our servers. - Retries & Delivery: We support up to 5 delivery attempts with exponential backoff on transient errors (non-2xx responses or timeouts).
The delivery history includes the endpoint, event type, status, HTTP response, attempt count, and time. Failed deliveries can be retried from the dashboard after the endpoint issue is corrected. Use your own event or audit stream when you need every internal event, including events that had no subscribed endpoint.