Webhooks
Webhooks let you subscribe to events happening in the k-ID Engine as they happen, as opposed to polling an API to see if data is available.
What are webhooks?
Webhooks can be used for a variety of purposes, such as:
- Handling challenge completion results
- Handling age verification results
- Handling changes in the k-ID Session
Setting up webhooks
Webhooks are configured in the Compliance Studio, by specifying a URL that the k-ID Engine calls when an event occurs. The URL must be a secure HTTPS URL. The k-ID Engine sends a POST request to the URL with a JSON payload that contains the event data.
Webhooks are associated with individual Products. You can use the same endpoint for all of your k-ID Products if you have more than one, but it's important to note that you must retrieve the correct Product-specific k-ID API Key to make API calls (for example /session/get).
Webhooks can be configured in the Developer Settings section of your product in the Compliance Studio.

Webhook event structure
The JSON payload sent to the webhook URL contains the following fields:
eventType- The type of event that occurred.data- The data associated with the event.
An X-Event-Type header is also sent with the event type.
Validating webhook requests
Webhooks are sent over the public internet, so it's important to validate that the requests are coming from k-ID. This is done by verifying the event payload signature by using the configured webhook secret.
All requests include the following headers:
X-Signature-Timestamp- The timestamp of the request, in UNIX epoch seconds.X-Signature-Hmac-Sha256- The HMAC SHA-256 keyed-hash of the UTF-8 encoded timestamp and request body concatenated together, using the webhook secret as the key, encoded as a lowercase hexadecimal string.
If the signature is invalid, the request should be rejected with a 401 status code. Webhook requests with validated signatures can be processed and accepted with a 200 status code.
Example validation code
const crypto = require("crypto");
// Your webhook secret, configured in the [Compliance Studio](/compliance-studio/products/creating-new-product).
const SECRET = "your-secret";
const timestamp = req.get("X-Signature-Timestamp");
const signature = req.get("X-Signature-Hmac-Sha256");
const body = req.rawBody; // Raw request body, as a string.
// Compute the expected signature.
const hmac = crypto.createHmac("sha256", SECRET);
hmac.update(timestamp + body);
const expectedSignature = hmac.digest("hex");
// Compare signatures securely.
if (
!crypto.timingSafeEqual(
Buffer.from(signature, "hex"),
Buffer.from(expectedSignature, "hex")
)
) {
return res.status(401).end("Unauthorized");
}
Event types
| Event Type | Description |
|---|---|
Challenge.StateChange | Emitted when a parental consent challenge changes state |
Verification.Result | Emitted with the result of a verification attempt |
Account.Delete | Emitted when an account is deleted |
AgeAssurance.Result | Emitted with the result of an Age Assurance evaluation (deprecated, replaced by Verification.Result) |
ParentalConsent.Granted | Emitted when parental consent is granted |
Session.ChangePermissions | Emitted when session permissions are modified by a parent |
Session.Delete | Emitted when a session is deleted |
Test | Used to verify that the webhook is working correctly |