Overview
A webhook serves as an efficient notification mechanism that triggers when specific events take place within SAIVA. For instance, when there's an occurrence like a daily risk assessment or when reports that aggregate daily risk predictions across facilities are prepared for distribution, SAIVA AI dispatches a JSON payload.
This payload, encapsulating details relevant to the report, is securely transmitted using an HTTP POST request to a predefined endpoint URL.
Creating a webhook
To initiate the integration process, go to the Integrations
section within MySAIVA, which can be found at app.saiva.ai and is accessible to enterprise customers:
Note:
1. Integrations need to be enabled for your organization
2. You must be an Org Administrator in order to access this function
Choose Webhooks and click on Connect
to enter the setup screen.
The next screen contains a summary of all your current webhooks and will initially show an empty state:
Click on Create Webhook
to define your first webhook and enter all the required configuration fields:
- Webhook Name: Your unique webhook name.
- This value will appear in the payload's web_hook_name property.
- Endpoint URL: Your endpoint URL. Must start with https://
- Report Type: Choose the type of report from the dropdown menu. Currently, the Webhooks support these reports:
- Daily Risk Report
- Cross Facility Risk Report
- Quality Measure (QM): Select the predicted quality measure from the dropdown, depending on your product subscription:
- UPT
- RTH
- Facility list: Select All Facilities or specific facility names to include in the payload
Click Create
to create & save your webhook. A new screen will now show the Secret value associated with this webhook:
Copy the secret value by clicking the Copy
button and use it in your code to validate the signature of the incoming event. See the Authentication section for more information about how this signature should be used in your code.
Testing your webhook
You can test your webhook immediately after saving or from the Edit Webhook screen:
Start your webhook endpoint server. You can download some samples for node.js and Python from the saiva-api repository.
Note: Make sure you include the copied secret value in your code!
Click on Test
to initiate a test ping to the endpoint with the signature header based on the current secret and a sample, one-record payload. If the test succeeds, your webhook is complete! Next, implement your payload-specific logic in the code.
Each delivery will also include a saiva-event-id header property indicating a unique id associated with this delivery.
After your webhook has been created, from this screen, you can also:
- Update your webhook configuration: Modify the desired fields and click
Save
to save your new configuration. - Regenerate the webhook secret from this screen by clicking the
Re-generate
button. Remember to update your code with the new secret value!
When you're ready to go live, make sure you set the Enable
switch so that your webhook can be invoked whenever a new report is available (see the Service Level Agreement section).
Defining and managing multiple webhooks
You can define additional webhooks as long as settings do not overlap and by abiding the following rules:
- Each webhook must have a unique name, regardless of the configuration
- You cannot define multiple webhooks with the exact same QM, list of facilities and Report Type
- You may use the same endpoint for multiple webhooks. Make sure, however, that the payload doesn't create any code logic conflicts and that your code supports multiple secrets (refer to the Authentication section on this page).
A duplicate webhook error will be shown upon save if uniqueness is violated.
You can manage your list of active webhooks from the Webhooks integration screen:
- Click on
Edit
(pencil) to show the Edit Webhook screen - Use the Enabled/Disabled switch to set the active state of your webhook
- Use the
Delete
(trashcan) button to delete your webhook
If your webhooks returned an error upon creation or after all possible retries have been exhausted (see: Retry Policy) it will be disabled. A corresponding message will reflect its disabled state:
Developing webhooks locally
To set up your webhook for local development, you'll require a Reverse Proxy. This lets you direct traffic from a public URL to your local development environment. Several free and paid tools are available to create a secure, public HTTP URL. If you'd like suggestions, please feel free to reach out to me. support@saiva.ai.
Service Level Agreement
For daily_risk_report and cross_facility_risk_report, the webhook will be invoked once a day by 8:00 am Eastern Standard Time. SLA is successful only if the webhook call is successful. If no data is available, the webhook won't be posting data to the webhook.
Authentication
SAIVA AI implements a security mechanism for webhook authentication by employing a digital signature. This signature is crafted using a secret key provided during the webhook setup alongside the request body. The resulting data is encapsulated in the signature header property. The process to calculate the signature is as follows:
HMAC-SHA256 = {Base64(HmacSHA256(body_bytes, CLIENT_SECRET))}
To verify the request came from SAIVA, compute an HMAC digest using your secret key and the body and compare it to the signature portion (after the space) contained in the header. If they match, you can be sure the webhook was sent from SAIVA. Otherwise, ensure your code returns an unspecific error immediately without invoking additional logic.
This signature header property contains the SHA algorithm used to generate the signature, a space, and the signature itself.
signature: sha256 HMAC-SHA256
e.g. signature: sha256 37d2725109df92747ffcee59833a1d1262d74b9703fa1234c789407218b4a4ef
Important: Implementation of signature verification is not mandatory for the webhook to function correctly, but is highly recommended in order to make sure your connected application is protected from denial-of-service and that it will not accidentally leak any information to unauthorized callers.
On the receiving end, this is how you verify the received HMAC
TypeScript example:
import crypto from 'crypto';
...
const verifyHmac = (
receivedHmacHeader: string,
receivedBody: any,
secret: string
): boolean => {
const hmacParts = receivedHmacHeader.split(' ')
const receivedHmac = hmacParts[1]
const hash = crypto
.createHmac('sha256', secret)
.update(receivedBody)
.digest('hex')
return receivedHmac == hash
}
JavaScript example:
const crypto = require('crypto');
...
const verifyHmac = (
receivedHmacHeader,
receivedBody,
secret
) => {
const hmacParts = receivedHmacHeader.split(' ')
const receivedHmac = hmacParts[1]
const hash = crypto
.createHmac('sha256', secret)
.update(receivedBody)
.digest('hex')
return receivedHmac == hash
}
Python example:
import hashlib, hmac
...
def verifyHmac(receivedHmacHeader, receivedBody, secret): hmacParts = receivedHmacHeader.split(' ') receivedHmac = hmacParts[1] hash = hmac.new(bytes(secret, 'UTF-8'), receivedBody, hashlib.sha256).hexdigest() return receivedHmac == hash
Note: If you are using the same endpoint to service multiple webhooks please make sure you add support in your code for verification of multiple signatures containing each webhook secret
Payload Description
Overview
The payload will vary depending on the selection of the Report Type. SAIVA plans to add additional report types in the future and will publish their payload schema on the saiva-api Github repository.
Testing and pinging
During the webhook configuration process, when enabling/disabling changes or whenever the webhook is tested from the UI, SAIVA AI will issue special requests denoted in the type property as either "ping" or "test" to indicate the webhook's functionality & integrity is being tested. In both cases, the consuming party should return 200 Ok, otherwise the webhook will be disabled.
Ping & Test Examples:
{
"version": "v1",
"type": "ping"
}
{
"version": "v1",
"type": "test",
...
// Additional payload properties follow
}
Report Type: daily_risk_report
Example:
The payload will contain an array of report objects, including FacilityRiskReport, one per facility.
{
"version": "v1",
"web_hook_name": "Sample UPT Daily Report For 10 Facilities", // From user webhook setting
"report_type": "daily_risk_report",
"qm_type: "model_upt",
"report_date": "04/13/2024",
"client": "Sample",
"payload_length": 10,
"payload": [
{
// 1st facility risk report as FacilitRiskReport object
},
...
{
// 10th facility risk report FacilityRiskReport object
}
]
}
See DailyRiskReport.json schema on GitHub.
Report Type: cross_facility_risk_report
Example:
The payload will contain an array of report objects FacilityRiskReport
{
"version": "v1",
"web_hook_name": "Cross Facility For 10 Facilities", // From user webhook setting
"report_type": "cross_facility_risk_report",
"report_date": "04/13/2024",
"client": "Sample",
"qm_type: "model_upt",
"payload_length": 10,
"payload": [
{
// 1st facility risk report as FacilitRiskReport object
},
...
{
// 10th facility risk report FacilityRiskReport object
}
]
}
Schema:
See CrossFacilityReport.json schema on GitHub.
Retry policy
In the event of a failed webhook request (due to timeout, a non-HTTP 200 response, or network issues), SAIVA will attempt a maximum of 5 retries according to the following algorithm:
RETRY_DELAY_MINUTES = [1, 15, 60, 120, 240]
sidekiq_retry_in do |index, _exception|
seconds_delay = (RETRY_DELAY_MINUTES[index] || RETRY_DELAY_MINUTES.last) * 60
offset = rand(30) * (index + 1)
seconds_delay + offset
end
This formula increases the time between each retry while assigning a random number of seconds to avoid consistent failures from overload or contention.
SAIVA will attempt 5 retries over the course of 7 hours. When all attempts have been exhausted, the webhook will be disabled and an error message will be sent to the webhook owner via email.
The table below outlines the estimated wait time for each retry request, assuming that rand(30) always returns 0:
Retry number | Next retry in | Total waiting time |
---|---|---|
1 | 1m | 0h 1m |
2 | 15m | 0h 16m |
3 | 60m | 1h 16m |
4 | 120m | 3h 16m |
5 | 240m | 7h 16m |
Email notifications to the registered email address of the owner of the webhook will be sent in the following events:
- Whenever the first attempt fails (warning)
- Whenever the last attempt fails (fatal error, webhook disabled)
Code Samples
You can find an example of node.js webhook implementation for node.js and Python in the saiva-api Github repository.
Get Help
For questions and support issues, don't hesitate to get in touch with support@saiva.ai
Comments
0 comments
Please sign in to leave a comment.