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:

mermaid
Rendering diagram...

Event Types

You can subscribe your endpoints to specific events from this catalog:

DomainEventTrigger
Licensinglicense.createdLicense key generated via dashboard or REST API
license.updatedLicense key fields modified
license.enabledLicense activated/unblocked
license.disabledLicense deactivated/blocked
license.deletedLicense key deleted
license.activations_resetActivation count reset
license.offline_signedOffline license file signed
Devicesdevice.activatedREST API activation succeeds
device.deactivatedREST API deactivation succeeds
Floatingfloating_session.checked_outFloating seat checkout or extension
floating_session.checked_inFloating seat checkin
floating_session.revokedVendor force-revokes floating session
floating_session.limit_hitCheckout rejected (concurrent limit)
Productsproduct.createdProduct created
product.updatedProduct updated or toggled
product.deletedProduct deleted
Customerscustomer.createdCustomer created
customer.updatedCustomer updated
customer.disabledCustomer deactivated
customer.enabledCustomer reactivated
customer.deletedCustomer 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 identifier
  • Keymint-Delivery-Id — Unique delivery attempt identifier
  • Keymint-Event-Type — Event type string
  • Keymint-Timestamp — Unix timestamp (seconds)
  • Keymint-Signaturet=<timestamp>,v1=<hex_hmac>

Verification Steps

  1. Parse the timestamp t and signature v1 from the Keymint-Signature header.
  2. Verify the timestamp is fresh (e.g. within 5 minutes) to defend against replay attacks.
  3. Concatenate the timestamp and raw body payload separated by a dot: signed_payload = timestamp + "." + raw_request_body
  4. Calculate the HMAC-SHA256 signature using your endpoint's signing secret.
  5. Use a timing-safe comparison to verify the computed hash matches the received v1 signature.

Example Verification (Node.js)

javascript
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.