Webhooks
Lynx uses webhooks to send notifications to the client application when an event of "interest" occurs. A number of Lynx API calls (such as enrollment API) require additional time for the processing to complete. In such cases, the API being invoked returns a response immediately with a success code - however Lynx will notify the client application using a pre-registered webhook once the entire process completes.
New event types are continuously being added to the platform. Clients have the option of subscribing to events that are of interest. It is up to you (the client) to decide which events you want to process and how.
Create Webhook API
Webhooks can be created using the Lynx Client Dashboard (under the Settings menu) or via API call.
| Property | Value |
|---|---|
| Method | POST |
| URL | https://dev.lynx-fh.co/clients/webhooks |
| Description | Adds a configuration webhook URL for a client organization |
| Auth | Bearer JWT |
Example Request
{
"data": {
"clientOrg": {
"name": "Health_Plan_ABC_Division"
},
"clientOrgWebHook": {
"url": "https://your-app.com/webhooks/lynx",
"encryptionIndicator": true,
"deliveryMode": "AtLeastOnce"
}
},
"idempotency": {
"idempotencyKey": "cf82639c-e3b6-4d51-9871-0e452a2b1566"
}
}| Field | Type | Description |
|---|---|---|
clientOrg.name | string | The name of your client organization |
clientOrgWebHook.url | string | The endpoint URL where Lynx will send webhook event notifications |
encryptionIndicator | boolean | Set to true to encrypt the webhook payload using AES-256-GCM. A secret key and IV will be provided |
deliveryMode | string | AtLeastOnce (retries on failure) or AtMostOnce (single delivery attempt) |
idempotencyKey | string | A unique identifier (UUID) to prevent duplicate webhook registrations |
Payload Encryption
Webhooks can be configured to encrypt the message payload. A secret key and an initialization vector are provided as part of the response when a webhook is created.
The encryption is based on the Advanced Encryption Standard (AES-256) - a symmetric-key algorithm. Below are code snippets on how to decrypt an encrypted payload, based on the secret key and initialization vector:
public static String decrypt(String secretKey, String initializationVector, String cipherText) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
// Initialize GCM Parameters
// Same base64EncodeKey, IV and GCM Specs are to be used for encryption and decryption.
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(TAG_BIT_LENGTH, Base64.getDecoder().decode(initializationVector));
Cipher decryptCypher = Cipher.getInstance(AES);
decryptCypher.init(Cipher.DECRYPT_MODE, convertStringToSecretKey(secretKey), gcmParameterSpec, drbgSecureRandom());
byte[] plainTextArray = null;
plainTextArray = decryptCypher.doFinal(Base64.getDecoder().decode(cipherText));
return new String(plainTextArray);
}
/**
* Create a SecretKey object from a given base64 secretKey string
* @param secretKey inbound secret key as string encoded in base64
* @return the SecretKey type object
*/
public static SecretKey convertStringToSecretKey(String secretKey) {
byte[] decodedKey = Base64.getDecoder().decode(secretKey);
return new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
}// NPM module required to decrypt (npm install crypto)
const crypto = require('crypto');
/**
* The decrypt function decrypts the inbound encrypted message. All inbound
* parameters are base64 encoded.
*/
const decrypt = function(encryptedMsg, secret, iv) {
// decode base64 message
const bufferData = Buffer.from(encryptedMsg, 'base64');
// separate message body and tag from message
let msg = bufferData.slice(0, bufferData.length - 16);
let authTag = bufferData.slice(bufferData.length - 16, bufferData.length);
// decode base64 secret and init vector
let decodedSecret = Buffer.from(secret, 'base64');
let decodedIV = Buffer.from(iv, 'base64');
// decrypt message body
let decipher = crypto.createDecipheriv('aes-256-gcm', decodedSecret, decodedIV);
decipher.setAuthTag(authTag);
let decipheredText = decipher.update(msg, 'utf8');
decipheredText += decipher.final('utf8');
console.log(decipheredText)
};Delivery Mode
Lynx supports two methods of delivery attempts for the webhook subscriptions:
| Delivery Mode | Definition |
|---|---|
| Single (at most once) | An attempt will be made to deliver a single webhook event to the specified URL. If the delivery fails for any reason (timeout or HTTP response code other than 200), the event will not be retried. |
| At least once | An attempt will be made to deliver a webhook event to the specified URL. If the delivery fails for any reason (timeout or HTTP response code other than 200), the event will be retried multiple times (every 5 minutes) until an HTTP response code of 200 is received. |
Steps to Receive Webhooks
Steps to Receive Webhooks
You can start receiving event notifications in your app using the steps in this section
- Identify the events you want to monitor and the event payloads to parse.
- Configure a Lynx client webhook endpoint as an HTTP endpoint (URL) on your local server.
- Handle requests from Lynx by parsing each event object and returning 2xx response status codes.
Webhooks can be tested locally via https://ngrok.com or remotely via https://webook.site. Both provide unique URLs to use for your webhook and capture incoming requests for examination.
Updated about 1 month ago
