Webhook & callback signing models

LicenseChain uses three separate signing models. Do not mix secrets, headers, or canonicalization rules between them.

Quick comparison

Model Service Header Signed material
Core API webhooks api.licensechain.app X-Webhook-Signature Raw JSON request body (UTF-8 bytes)
Pay merchant webhooks pay.licensechain.app x-lc-pay-signature {timestamp}.{rawJsonBody}
Mirror redirect HMAC Browser redirect to your site signature query param Canonical query string (sorted keys, no signature)

1. Core API outbound webhooks (HMAC)

Registered with POST /v1/webhooks on the Core API. Used for license lifecycle events (license.created, license.revoked, etc.) and platform notifications.

  • Secret: webhook secret returned when you create the endpoint (or your custom secret if provided).
  • Header: X-Webhook-Signature โ€” HMAC-SHA256 hex digest of the exact raw JSON body.
  • Optional: X-Webhook-Timestamp for replay protection (recommended in your handler).
  • Algorithm: HMAC-SHA256; compare with constant-time equality (crypto.timingSafeEqual).

Full setup: Webhook Setup (Core API). Multi-language verify samples: API examples.

2. Pay merchant webhooks (x-lc-pay-signature)

Delivered by LicenseChain Pay when payment lifecycle events occur (e.g. payment.succeeded, subscription.created, subscription.canceled). Configured per product via Pay / Dashboard.

  • Secret: product callbackSecret (same secret family as Mirror checkout; rotate via product API).
  • Headers: x-lc-pay-signature, x-lc-pay-timestamp, x-lc-pay-event-id, x-lc-pay-event-type, x-lc-pay-idempotency-key.
  • Signed message: UTF-8 string {x-lc-pay-timestamp}.{rawJsonBody} (timestamp dot raw body).
  • Algorithm: HMAC-SHA256, lowercase hex digest in x-lc-pay-signature.

Delivery, retries, and ops endpoints: Callbacks & Webhooks (Pay).

subscription.canceled: Pay emits this event when a subscription is canceled. To cancel programmatically via the Core API, use POST /v1/subscriptions/:id/cancel once that route is available in your API deployment (see Subscriptions).

3. Mirror redirect HMAC

After checkout on pay.licensechain.app, the buyer is redirected to your thanks URL with query parameters such as status, LCG (license key), and signature. This is not an HTTP POST webhook โ€” verify server-side on the return URL before fulfilling access.

  • Secret: product callbackSecret (never expose in client-side JavaScript).
  • Param: signature โ€” HMAC-SHA256 hex over the canonical query string.
  • Canonicalization: sort parameter keys alphabetically, exclude signature, URL-encode key/value pairs, join with &.
  • Fail closed: reject missing/invalid signatures; do not trust LCG or status alone.
  • Second check: call POST /api/checkout/mirror/validate with license + email before granting access.

SDK helpers: Mirror SDK (verifyCallbackSignature, verifyPurchase). Pay mirror API: Pay Mirror API.

Security checklist (all models)

  • Store secrets in environment variables or a secrets manager โ€” never commit to git or ship in mobile/desktop clients.
  • Use HTTPS for every webhook and return URL endpoint.
  • Verify signatures with constant-time comparison before parsing business logic.
  • Treat Pay callbackSecret as dual-purpose: Mirror redirect signing and Pay merchant webhook signing.
  • See Security Best Practices for JWT, API keys, and fulfillment hardening.