Set up webhooks
This guide explains how to create, verify, enable and process webhook subscriptions.
Step 1: Create your endpoint
Create the endpoint that will receive the event notifications that you subscribed to.
Your endpoint URL must be able to handle both POST and GET requests. Event notifications are sent to the URL via POST requests in the format described in Step 6. A challenge-response flow to verify that you own the URL is initiated with a GET request, as described in Step 3. Your endpoint must respond to the challenge with an HTTP success status code (2xx
) and pass the request's X-Verification-Key
header value in the response's JSON payload:
{
"key": "<key-value>"
}
Where <key-value>
is the value received in the X-Verification-Key
header.
Step 2: Create webhook
You can create a webhook via the Admin Portal or the Webhooks APIs.
In this example, the API is used to create a webhook:
curl -i -X POST \
'https://api.transmitsecurity.io/cis/v1/webhooks' \
-H 'Authorization: Bearer 91827321837bdfjf' \
-H 'Content-Type: application/json' \
-d '{
"uri": "https://acme.com/external/transmit-user-events",
"api_key": "34dc49a6-0fae-4ce6-97c4-ca9ad4123b0d",
"subscribed_events": [
"User created",
"User deleted"
],
"name": "User info",
"description": "Send notifications whenever a user is created or deleted"
}'
Note
Make sure you have a valid client access token to authorize the request. Since this is a tenant-level operation, the token will need tenant-level authorization (based on a Management Application). If you don't already have a token, you'll need to get one. Learn more
The above request creates a webhook named User info
, subscribes to the User created
and User deleted
events, and defines the URL to which notifications are sent as https://acme.com/external/transmit-user-events
. It also sets a value for the api_key
, which should be used to validate your the event notifications were sent by Mosaic.
The response to this request includes an autogenerated webhook_id
, which is used to identify the webhook in requests.
Step 3: Verify webhook
Before Mosaic sends notifications to your webhook, its URL must be verified. This is done with a challenge-response flow, where Mosaic sends a unique key to the webhook's URL in a GET request (in the X-Verification-Key
header) and expects to receive the header value in the response payload. Once the response is successfully received, the webhook is considered verified.
Note
Each webhooks only needs to be verified once.
To perform a verification flow:
-
Send a POST request to the
Webhook Verification API
, where
<webhook-id>
is the ID of the webhook you want to verify (the ID generated in step 2 ):curl -i -X POST \ https://api.transmitsecurity.io/cis/v1/webhooks/verify/<webhook-id> \ -H 'Authorization: Bearer 91827321837bdfjf' \
Upon receiving this request, Mosaic sends a challenge to your webhook endpoint using a GET request like this:
Accept: application/json, text/plain, */* \ content-length: 0 \ Host: acme.com \ user-agent: PostmanRuntime/7.29.2 \ Via: 1.1 google \ X-API-Key: 34dc49a6-0fae-4ce6-97c4-ca9ad4123b0d \ X-Scheme: https \ X-Verification-Key: GoO8Z3hJxx826qTmvwepy \
-
Upon receiving this challenge, your endpoint must:
-
Validate the
X-API-Key
header value is identical to theapi_key
value used to create the webhook in step 2 . -
Retrieve the
X-Verification-Key
header value and return it as part of the response's JSON payload. -
Respond with a success code (
2xx
).
Here is a sample code snippet:
// Verifies the webhook webhook.define('/transmit-user-events','GET', function(req, res) { // Retrieve the header value var key = req.get("X-Verification-Key"); var mosaic_webhook_token = "34dc49a6-0fae-4ce6-97c4-ca9ad4123b0d"; // Make sure the request token is valid if (req.get("X-API-Key") != mosaic_webhook_token) { return res.send(400, 'Invalid request'); } // Set the response type res.type('application/json'); // Set the status code of the response. res.status(200); // Send the key value in the body res.json({ "key": key });
Once the challenge is completed, Mosaic returns a
201
status code to your initial verification call with this JSON body:{ "verified": true }
-
Validate the
Step 4: Enable webhook
Notifications are only sent to a webhook after you enable it, either from the Admin Portal and via the API.
To enable a webhook via the API, send a PATCH request to the webhooks
endpoint, where <webhook-id>
is the ID of the webhook you want to enable (the ID generated in step 2).
curl -i -X PATCH \
'https://api.transmitsecurity.io/cis/v1/webhooks/<webhook-id>' \
-H 'Authorization: Bearer 91827321837bdfjf' \
-H 'Content-Type: application/json' \
-d '{
"enabled": true
}'
Step 5: Validate notification
Whenever you receive an event notification, your endpoint needs to validate the request to make sure it was indeed sent by Mosaic. This is done by checking that the X-API-Key
header value is identical to the api_key
value used to create the webhook in step 2. Once validated, return a 200 response.
Note
If an HTTP success status code (2xx
) response is not received within 3 seconds, Mosaic will attempt to send the notification again (up to two more times).
Step 6: Parse event data
All Mosaic webhooks use the same schema, which can be parsed as needed.
Webhooks contain a JSON body, with the following structure:
Field | Type | Description |
---|---|---|
event_id |
String | The ID of the event. |
tenant_id |
String | The ID of the tenant in which the event was performed. |
app_id |
String | The ID of the app for which the event was performed. |
event_type |
String | The event type, as described below. |
timestamp |
String | The time the event occurred, using the ISO 8601 format. |
payload |
Object | Object containing user information |
The event_type
may correspond to one of these values:
Event | Description |
---|---|
User created |
User was created by an admin, or implicitly upon authenticating |
User updated |
User's profile was updated |
User deleted |
User was deleted |
User added to app |
User was associated with an app |
User removed from app |
User was removed from an app |
User logged in |
User successful authenticates |
User logged out |
User logs out of the session (via Logout API) |
User suspended |
User was suspended |
User unsuspended |
User status was changed from suspended to active |
User password lock |
A lockout applies on user password authentication |
Orchestrated user login |
User was logged in within an orchestrated journey |
Failed OTP attempt |
Last email or phone verification with OTP failed |
The payload
object contains these fields:
Field | Type | Description |
---|---|---|
user_id |
String | The ID of the user for which the action was performed. |
created_at |
Number | The time the user was created, as a unix-epoch encoded timestamp in milliseconds. |
updated_at |
Number | The last time the user was updated, as a unix-epoch encoded timestamp in milliseconds. |
status |
String | The user's status, which can be Active , Pending , or Suspended . |
email |
Object | Object containing the user's primary email address (value , string) and verification state (email_verified , boolean). |
phone_number |
Object | Object containing the user's primary mobile (value , string) and verification state (phone_number_verified , boolean). |
Here is an example payload:
{
"event_id": "tdl4yENhzpZ-GvbAx5cGQ",
"tenant_id": "wdrCjEPYOLQNQrqmXLnDt",
"app_id": "DSaI3VGBp4nepRE656XPB",
"event_type": "User created",
"timestamp": "2022-07-21T18:15:34.134Z",
"payload": {
"user_id": "ue3N8fKgygwfkxC7GXhFV",
"created_at": 1658427334127,
"updated_at": 1658427334127,
"status": "Pending",
"email": {
"value": "user@acme.com",
"email_verified": true
},
"phone_number": {
"value": "+19999999999",
"phone_number_verified": true
}
}
}